From 9767eba8d1da85749afa1b9dfb63ddfd3f5d5191 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Sun, 31 Jul 2011 16:43:00 +0530 Subject: Background task to periodically sync cluster-server mapping --- .../core/constants/GlusterConstants.java | 2 + .../management/core/utils/GlusterCoreUtil.java | 15 +- .../scripts/multicast-discover-servers.py | 90 +++++++++++ .../WebContent/scripts/vmware-discover-servers.py | 90 ----------- .../resources/v1_0/AbstractServersResource.java | 38 ----- .../resources/v1_0/DiscoveredServersResource.java | 11 +- .../resources/v1_0/GlusterServersResource.java | 136 +++-------------- .../server/services/GlusterServerService.java | 165 +++++++++++++++++++++ .../server/tasks/ServerDiscoveryTask.java | 77 ---------- .../management/server/tasks/ServerSyncTask.java | 154 +++++++++++++++++++ .../management/server/utils/GlusterUtil.java | 2 +- .../src/spring/gluster-server-base.xml | 11 +- 12 files changed, 456 insertions(+), 335 deletions(-) create mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py delete mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py delete 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/services/GlusterServerService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java (limited to 'src') diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java index 51b53241..cbc51b10 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/constants/GlusterConstants.java @@ -38,6 +38,8 @@ public class GlusterConstants { public static final String ON = "on"; public static final String OFF = "off"; + public static final String NONE = "none"; + public static final String STATS_PERIOD_1DAY = "1d"; public static final String STATS_PERIOD_1WEEK = "1w"; public static final String STATS_PERIOD_1MONTH = "1m"; diff --git a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java index 7b1eec36..e5624954 100644 --- a/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java +++ b/src/com.gluster.storage.management.core/src/com/gluster/storage/management/core/utils/GlusterCoreUtil.java @@ -97,18 +97,17 @@ public class GlusterCoreUtil { boolean caseInsensitive) { return getEntity(entityList, searchEntity.getName(), caseInsensitive) != null; } + + public static boolean containsEntityWithName(List entityList, String searchName, + boolean caseInsensitive) { + return getEntity(entityList, searchName, caseInsensitive) != null; + } public static T getEntity(Collection entityList, String searchEntityName, boolean caseInsensitive) { - if (caseInsensitive) { - searchEntityName = searchEntityName.toUpperCase(); - } - for (T entity : entityList) { String nextEntityName = entity.getName(); - if (caseInsensitive) { - nextEntityName = nextEntityName.toUpperCase(); - } - if (nextEntityName.equals(searchEntityName)) { + if (nextEntityName.equals(searchEntityName) + || (caseInsensitive && nextEntityName.equalsIgnoreCase(searchEntityName))) { return entity; } } diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py b/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py new file mode 100755 index 00000000..e9ae8666 --- /dev/null +++ b/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import socket +import signal +import struct +import syslog +import Globals +import Common +import time +from XmlHandler import * + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + sendtime = time.time() + socketSend.sendto("ServerDiscovery" % (sendtime), (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if not response: + continue + dom = XDOM() + dom.parseString(response[0]) + if not dom: + continue + if dom.getTextByTagRoute("request.name"): + continue + responsetime = dom.getTextByTagRoute("response.time") + servername = dom.getTextByTagRoute("response.servername") + if responsetime == str(sendtime): + servers.append(servername) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Common.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + for server in servers: + print server + except IOError: + Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py b/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py deleted file mode 100755 index e9ae8666..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/vmware-discover-servers.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import socket -import signal -import struct -import syslog -import Globals -import Common -import time -from XmlHandler import * - -class TimeoutException(Exception): - pass - -def timeoutSignal(signum, frame): - raise TimeoutException, "Timed out" - -def serverDiscoveryRequest(multiCastGroup, port): - servers = [] - # Sending request to all the servers - socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) - socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) - - # Waiting for the response - socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - socketReceive.bind(('', port)) - mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) - - socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - sendtime = time.time() - socketSend.sendto("ServerDiscovery" % (sendtime), (multiCastGroup, port)) - - try: - while True: - response = socketReceive.recvfrom(200) - if not response: - continue - dom = XDOM() - dom.parseString(response[0]) - if not dom: - continue - if dom.getTextByTagRoute("request.name"): - continue - responsetime = dom.getTextByTagRoute("response.time") - servername = dom.getTextByTagRoute("response.servername") - if responsetime == str(sendtime): - servers.append(servername) - signal.signal(signal.SIGALRM, timeoutSignal) - signal.alarm(3) - except TimeoutException: - return servers - return None - -def main(): - syslog.openlog("discovery server request") - servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) - if not servers: - Common.log(syslog.LOG_ERR, "Failed to discover new servers") - sys.exit(-1) - - servers = set(servers) - try: - for server in servers: - print server - except IOError: - Common.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) - sys.exit(-1) - sys.exit(0) - -if __name__ == "__main__": - main() 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 deleted file mode 100644 index 8b4b6d99..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/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.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/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java index cb39746c..f6038b71 100644 --- 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 @@ -38,12 +38,21 @@ 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.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; @Component @Singleton @Path(RESOURCE_PATH_DISCOVERED_SERVERS) -public class DiscoveredServersResource extends AbstractServersResource { +public class DiscoveredServersResource extends AbstractResource { + @InjectParam + protected ServerUtil serverUtil; + + @InjectParam + protected GlusterUtil glusterUtil; + private List discoveredServerNames = new ArrayList(); public List getDiscoveredServerNames() { 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 index 525f4132..fa96c884 100644 --- 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 @@ -51,7 +51,6 @@ import javax.ws.rs.QueryParam; 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; @@ -60,7 +59,6 @@ import com.gluster.storage.management.core.exceptions.ConnectionException; import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; import com.gluster.storage.management.core.exceptions.GlusterValidationException; import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; import com.gluster.storage.management.core.model.ServerStats; import com.gluster.storage.management.core.model.TaskStatus; import com.gluster.storage.management.core.response.GlusterServerListResponse; @@ -68,10 +66,13 @@ import com.gluster.storage.management.core.response.ServerNameListResponse; 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.services.GlusterServerService; import com.gluster.storage.management.server.tasks.InitializeDiskTask; import com.gluster.storage.management.server.utils.CpuStatsFactory; +import com.gluster.storage.management.server.utils.GlusterUtil; import com.gluster.storage.management.server.utils.MemoryStatsFactory; import com.gluster.storage.management.server.utils.NetworkStatsFactory; +import com.gluster.storage.management.server.utils.ServerUtil; import com.gluster.storage.management.server.utils.SshUtil; import com.gluster.storage.management.server.utils.StatsFactory; import com.sun.jersey.api.core.InjectParam; @@ -80,7 +81,7 @@ 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 class GlusterServersResource extends AbstractResource { public static final String HOSTNAMETAG = "hostname:"; @@ -90,31 +91,30 @@ public class GlusterServersResource extends AbstractServersResource { @InjectParam private TasksResource taskResource; - @Autowired + @InjectParam private ClusterService clusterService; - @Autowired + @InjectParam private SshUtil sshUtil; - @Autowired + @InjectParam private CpuStatsFactory cpuStatsFactory; - @Autowired + @InjectParam private MemoryStatsFactory memoryStatsFactory; - @Autowired + @InjectParam private NetworkStatsFactory networkStatsFactory; - protected void fetchServerDetails(GlusterServer server) { - try { - server.setStatus(SERVER_STATUS.ONLINE); - serverUtil.fetchServerDetails(server); - } catch (ConnectionException e) { - server.setStatus(SERVER_STATUS.OFFLINE); - } - } - - + @InjectParam + private ServerUtil serverUtil; + + @InjectParam + private GlusterUtil glusterUtil; + + @InjectParam + private GlusterServerService glusterServerService; + @GET @Produces(MediaType.APPLICATION_JSON) public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @@ -129,26 +129,6 @@ public class GlusterServersResource extends AbstractServersResource { return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); } - private List getGlusterServers(String clusterName, boolean fetchDetails) { - List glusterServers; - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); - } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); - } - return glusterServers; - } - private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { if(fetchDetails == null) { // by default, fetch the server details @@ -171,7 +151,7 @@ public class GlusterServersResource extends AbstractServersResource { } try { - glusterServers = getGlusterServers(clusterName, fetchDetails); + glusterServers = glusterServerService.getGlusterServers(clusterName, fetchDetails); } catch (Exception e) { return errorResponse(e.getMessage()); } @@ -184,7 +164,6 @@ public class GlusterServersResource extends AbstractServersResource { } } - private List getServerNames(List glusterServers) { List serverNames = new ArrayList(); for(GlusterServer server : glusterServers) { @@ -193,42 +172,6 @@ public class GlusterServersResource extends AbstractServersResource { return serverNames; } - private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { - String errMsg = ""; - - for (GlusterServer server : glusterServers) { - try { - fetchServerDetails(server); - } catch (Exception e) { - errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; - } - } - return errMsg; - } - - private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { - 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); - } - - if (fetchDetails) { - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); - } - } - return glusterServers; - } - @GET @Path("{" + PATH_PARAM_SERVER_NAME + "}") @Produces(MediaType.APPLICATION_XML) @@ -247,49 +190,12 @@ public class GlusterServersResource extends AbstractServersResource { private Response getGlusterServerResponse(String clusterName, String serverName, String mediaType) { try { - return okResponse(getGlusterServer(clusterName, serverName), mediaType); + return okResponse(glusterServerService.getGlusterServer(clusterName, serverName, true), 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) { @@ -542,7 +448,7 @@ public class GlusterServersResource extends AbstractServersResource { return okResponse(new ServerStats(), mediaType); } - List serverNames = getServerNames(getGlusterServers(clusterName, false)); + List serverNames = getServerNames(glusterServerService.getGlusterServers(clusterName, false)); return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); } diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java new file mode 100644 index 00000000..e8bea530 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.services; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.server.data.ClusterInfo; +import com.gluster.storage.management.server.utils.GlusterUtil; +import com.gluster.storage.management.server.utils.ServerUtil; + +/** + * + */ +@Component +public class GlusterServerService { + @Autowired + protected ServerUtil serverUtil; + + @Autowired + private ClusterService clusterService; + + @Autowired + private GlusterUtil glusterUtil; + + public void fetchServerDetails(GlusterServer server) { + try { + server.setStatus(SERVER_STATUS.ONLINE); + serverUtil.fetchServerDetails(server); + } catch (ConnectionException e) { + server.setStatus(SERVER_STATUS.OFFLINE); + } + } + + public List getGlusterServers(String clusterName, boolean fetchDetails) { + List glusterServers; + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); + } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); + } + return glusterServers; + } + + private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { + 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); + } + + if (fetchDetails) { + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); + } + } + return glusterServers; + } + + private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { + String errMsg = ""; + + for (GlusterServer server : glusterServers) { + try { + fetchServerDetails(server); + } catch (Exception e) { + errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; + } + } + return errMsg; + } + + public GlusterServer getGlusterServer(String clusterName, String serverName, Boolean fetchDetails) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterValidationException("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 + "]"); + } + + return getGlusterServer(clusterName, serverName, onlineServer, fetchDetails); + } + + private GlusterServer getGlusterServer(String clusterName, String serverName, GlusterServer onlineServer, + Boolean fetchDetails) { + 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 (fetchDetails && server.isOnline()) { + fetchServerDetails(server); + } + return server; + } + + public boolean isValidServer(String clusterName, String serverName) { + try { + GlusterServer server = getGlusterServer(clusterName, serverName, false); + return server != null; + } catch(Exception e) { + return false; + } + } +} 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 deleted file mode 100644 index e5b8d726..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerDiscoveryTask.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * ServerDiscoveryTask.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.tasks; - -import java.util.ArrayList; -import java.util.List; - -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.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.v1_0.DiscoveredServersResource; -import com.gluster.storage.management.server.utils.ServerUtil; - -/** - * Task for auto-discovery of servers eligible to be added to the Gluster cluster. This task runs periodically and keeps - * the discovered server list at a common place. The server resource can then pick it and send to client whenever - * demanded. - */ -@Component -public class ServerDiscoveryTask { - private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; - - @Autowired - private ServerUtil serverUtil; - - @Autowired - private DiscoveredServersResource discoveredServersResource; - - @Autowired - private String environment; - - @Autowired - private PersistenceDao clusterDao; - - public void discoverServers() { - List serverNameList = new ArrayList(); - - ProcessResult result = serverUtil.executeGlusterScript(true, environment + SCRIPT_NAME_SFX, new ArrayList()); - if(result.isSuccess()) { - List existingServers = clusterDao.findBySQL("select name from server_info"); - String serverNames = result.getOutput(); - String[] parts = serverNames.split(CoreConstants.NEWLINE); - for(String serverName : parts) { - // The server discovery mechanism will return every server that has not been "peer probed". However we - // need to filter out those servers that are the "first" server of a new cluster, and hence are still - // not peer probed. - if(!existingServers.contains(serverName)) { - serverNameList.add(serverName); - } - } - } - - discoveredServersResource.setDiscoveredServerNames(serverNameList); - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java new file mode 100644 index 00000000..feb02354 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java @@ -0,0 +1,154 @@ +/** + * ServerDiscoveryTask.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.tasks; + +import java.util.ArrayList; +import java.util.List; + +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.GlusterConstants; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +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.data.ServerInfo; +import com.gluster.storage.management.server.resources.v1_0.DiscoveredServersResource; +import com.gluster.storage.management.server.services.ClusterService; +import com.gluster.storage.management.server.services.GlusterServerService; +import com.gluster.storage.management.server.utils.ServerUtil; + +/** + * Task for syncing server details. This performs two things:
+ * 1. Auto-discovery of servers eligible to be added to the Gluster cluster.
+ * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user + * adds/removes servers manually using the CLI. + */ +@Component +public class ServerSyncTask { + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private DiscoveredServersResource discoveredServersResource; + + @Autowired + private GlusterServerService glusterServerService; + + @Autowired + private String discoveryMechanism; + + @Autowired + private ClusterService clusterService; + + @Autowired + private PersistenceDao clusterDao; + + public void perform() { + discoverServers(); + syncClusterServerMapping(); + } + + private void syncClusterServerMapping() { + List clusters = clusterService.getAllClusters(); + for(ClusterInfo cluster : clusters) { + List servers = cluster.getServers(); + List actualServers = glusterServerService.getGlusterServers(cluster.getName(), false); + updateRemovedServers(cluster, servers, actualServers); + updateAddedServers(cluster, servers, actualServers); + } + } + + private void updateAddedServers(ClusterInfo cluster, List servers, List actualServers) { + List addedServers = findAddedServers(cluster.getName(), servers, actualServers); + for(String addedServer : addedServers) { + clusterService.mapServerToCluster(cluster.getName(), addedServer); + } + } + + private void updateRemovedServers(ClusterInfo cluster, List servers, List actualServers) { + List removedServers = findRemovedServers(servers, actualServers); + for(String removedServer : removedServers) { + clusterService.unmapServerFromCluster(cluster.getName(), removedServer); + } + } + + private List findRemovedServers(List servers, List actualServers) { + List removedServers = new ArrayList(); + + for(ServerInfo server : servers) { + if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { + removedServers.add(server.getName()); + } + } + return removedServers; + } + + private List findAddedServers(String clusterName, List servers, List actualServers) { + List addedServers = new ArrayList(); + for(GlusterServer actualServer : actualServers) { + if(!serverExists(servers, actualServer.getName())) { + addedServers.add(actualServer.getName()); + } + } + return addedServers; + } + + private boolean serverExists(List servers, String name) { + for(ServerInfo server : servers) { + if(server.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private void discoverServers() { + if(discoveryMechanism.equals(GlusterConstants.NONE)) { + return; + } + + List serverNameList = new ArrayList(); + + ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList()); + if(result.isSuccess()) { + List existingServers = clusterDao.findBySQL("select name from server_info"); + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + for(String serverName : parts) { + // The server discovery mechanism will return every server that has not been "peer probed". However we + // need to filter out those servers that are the "first" server of a new cluster, and hence are still + // not peer probed. + if(!existingServers.contains(serverName)) { + serverNameList.add(serverName); + } + } + } + + discoveredServersResource.setDiscoveredServerNames(serverNameList); + } +} \ No newline at end of file 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 642198df..f5d09ac2 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 @@ -84,7 +84,7 @@ public class GlusterUtil { @Autowired private ServerUtil serverUtil; - @InjectParam + @Autowired private TasksResource taskResource; public void setSshUtil(SshUtil sshUtil) { 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 76cd3082..3cf30ee4 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 @@ -12,19 +12,20 @@ + - + - + - - + + -- cgit From 8a27c576bbbeea95fc5a0e7b509ce68133619a05 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Sun, 31 Jul 2011 16:58:29 +0530 Subject: Renamed project and package com.gluster.storage.management.server to com.gluster.storage.management.gateway --- .../com.gluster.storage.management.gateway.cquery | 4 + .../com.gluster.storage.management.server.cquery | 4 - .../.project | 2 +- .../.pydevproject | 2 +- src/com.gluster.storage.management.server/.project | 2 +- .../.settings/org.eclipse.wst.common.component | 4 +- .../WebContent/WEB-INF/web.xml | 147 ++- .../build/glusterserver.ant | 2 +- .../gateway/constants/VolumeOptionsDefaults.java | 118 +++ .../management/gateway/data/ClusterInfo.java | 79 ++ .../management/gateway/data/GlusterDataSource.java | 48 + .../management/gateway/data/PersistenceDao.java | 113 +++ .../management/gateway/data/ServerInfo.java | 72 ++ .../management/gateway/filters/AuditFilter.java | 38 + .../filters/AuthenticationFailureFilter.java | 105 +++ .../filters/GlusterResourceFilterFactory.java | 31 + .../gateway/resources/v1_0/AbstractResource.java | 177 ++++ .../gateway/resources/v1_0/ClustersResource.java | 126 +++ .../resources/v1_0/DiscoveredServersResource.java | 150 ++++ .../resources/v1_0/GenericExceptionMapper.java | 54 ++ .../resources/v1_0/GlusterServersResource.java | 487 ++++++++++ .../gateway/resources/v1_0/KeysResource.java | 153 ++++ .../gateway/resources/v1_0/TasksResource.java | 194 ++++ .../gateway/resources/v1_0/UsersResource.java | 91 ++ .../gateway/resources/v1_0/VolumesResource.java | 988 +++++++++++++++++++++ .../security/GlusterUserDetailsService.java | 31 + .../management/gateway/security/UserAuthDao.java | 42 + .../gateway/services/ClusterService.java | 269 ++++++ .../gateway/services/GlusterServerService.java | 165 ++++ .../management/gateway/tasks/InitServerTask.java | 162 ++++ .../gateway/tasks/InitializeDiskTask.java | 168 ++++ .../management/gateway/tasks/MigrateBrickTask.java | 227 +++++ .../gateway/tasks/RebalanceVolumeTask.java | 134 +++ .../management/gateway/tasks/ServerSyncTask.java | 154 ++++ .../storage/management/gateway/tasks/Task.java | 112 +++ .../gateway/utils/AbstractStatsFactory.java | 168 ++++ .../management/gateway/utils/CpuStatsFactory.java | 36 + .../management/gateway/utils/GlusterUtil.java | 664 ++++++++++++++ .../gateway/utils/MemoryStatsFactory.java | 68 ++ .../gateway/utils/NetworkStatsFactory.java | 123 +++ .../management/gateway/utils/ServerUtil.java | 258 ++++++ .../storage/management/gateway/utils/SshUtil.java | 388 ++++++++ .../management/gateway/utils/StatsFactory.java | 31 + .../server/constants/VolumeOptionsDefaults.java | 118 --- .../management/server/data/ClusterInfo.java | 79 -- .../management/server/data/GlusterDataSource.java | 48 - .../management/server/data/PersistenceDao.java | 113 --- .../storage/management/server/data/ServerInfo.java | 72 -- .../management/server/filters/AuditFilter.java | 38 - .../filters/AuthenticationFailureFilter.java | 105 --- .../filters/GlusterResourceFilterFactory.java | 31 - .../server/resources/v1_0/AbstractResource.java | 177 ---- .../server/resources/v1_0/ClustersResource.java | 126 --- .../resources/v1_0/DiscoveredServersResource.java | 150 ---- .../resources/v1_0/GenericExceptionMapper.java | 54 -- .../resources/v1_0/GlusterServersResource.java | 487 ---------- .../server/resources/v1_0/KeysResource.java | 153 ---- .../server/resources/v1_0/TasksResource.java | 194 ---- .../server/resources/v1_0/UsersResource.java | 91 -- .../server/resources/v1_0/VolumesResource.java | 988 --------------------- .../server/security/GlusterUserDetailsService.java | 31 - .../management/server/security/UserAuthDao.java | 42 - .../management/server/services/ClusterService.java | 269 ------ .../server/services/GlusterServerService.java | 165 ---- .../management/server/tasks/InitServerTask.java | 162 ---- .../server/tasks/InitializeDiskTask.java | 168 ---- .../management/server/tasks/MigrateBrickTask.java | 227 ----- .../server/tasks/RebalanceVolumeTask.java | 134 --- .../management/server/tasks/ServerSyncTask.java | 154 ---- .../storage/management/server/tasks/Task.java | 112 --- .../server/utils/AbstractStatsFactory.java | 168 ---- .../management/server/utils/CpuStatsFactory.java | 36 - .../management/server/utils/GlusterUtil.java | 664 -------------- .../server/utils/MemoryStatsFactory.java | 68 -- .../server/utils/NetworkStatsFactory.java | 123 --- .../management/server/utils/ServerUtil.java | 258 ------ .../storage/management/server/utils/SshUtil.java | 388 -------- .../management/server/utils/StatsFactory.java | 31 - .../src/spring/gluster-server-base.xml | 16 +- 79 files changed, 6309 insertions(+), 6322 deletions(-) create mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery delete mode 100644 src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java create mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ClusterInfo.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/PersistenceDao.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ServerInfo.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuditFilter.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/GlusterResourceFilterFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java (limited to 'src') diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery new file mode 100644 index 00000000..346b39bf --- /dev/null +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery @@ -0,0 +1,4 @@ + + + + diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery deleted file mode 100644 index 346b39bf..00000000 --- a/src/com.gluster.storage.management.releng/com.gluster.storage.management.server.cquery +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/com.gluster.storage.management.server.scripts/.project b/src/com.gluster.storage.management.server.scripts/.project index beda33b7..110db62b 100644 --- a/src/com.gluster.storage.management.server.scripts/.project +++ b/src/com.gluster.storage.management.server.scripts/.project @@ -1,6 +1,6 @@ - com.gluster.storage.management.server.scripts + com.gluster.storage.management.gateway.scripts diff --git a/src/com.gluster.storage.management.server.scripts/.pydevproject b/src/com.gluster.storage.management.server.scripts/.pydevproject index 0a912df5..c327cd69 100644 --- a/src/com.gluster.storage.management.server.scripts/.pydevproject +++ b/src/com.gluster.storage.management.server.scripts/.pydevproject @@ -5,6 +5,6 @@ Default python 3.0 -/com.gluster.storage.management.server.scripts/src +/com.gluster.storage.management.gateway.scripts/src diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project index 259b3726..3e4dc06a 100644 --- a/src/com.gluster.storage.management.server/.project +++ b/src/com.gluster.storage.management.server/.project @@ -1,6 +1,6 @@ - com.gluster.storage.management.server + com.gluster.storage.management.gateway diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component index dbf56d1e..3d5a50bf 100644 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component +++ b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component @@ -1,10 +1,10 @@ - + - + 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 e810c2ed..631788ff 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 @@ -1,86 +1,73 @@ - - glustermg - - index.html - index.htm - index.jsp - default.html - default.htm - default.jsp - - - - - contextConfigLocation - + + glustermg + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + + contextConfigLocation + classpath:spring/gluster-server-security.xml classpath:spring/gluster-server-base.xml - - - org.springframework.web.context.ContextLoaderListener - - - org.springframework.web.context.request.RequestContextListener - - - - - gluster-resources-1.0 - - com.sun.jersey.spi.spring.container.servlet.SpringServlet - - com.sun.jersey.config.property.packages - com.gluster.storage.management.server.resources.v1_0 - - - com.sun.jersey.spi.container.ResourceFilters - com.gluster.storage.management.server.filters.GlusterResourceFilterFactory - - 1 - - - gluster-resources-1.0 - /1.0/* - - - - - JnlpDownloadServlet - jnlp.sample.servlet.JnlpDownloadServlet - - - JnlpDownloadServlet - *.jnlp - - - JnlpDownloadServlet - *.jar - - - - - springSecurityFilterChain - + + + org.springframework.web.context.ContextLoaderListener + + + org.springframework.web.context.request.RequestContextListener + + + gluster-resources-1.0 + com.sun.jersey.spi.spring.container.servlet.SpringServlet + + com.sun.jersey.config.property.packages + com.gluster.storage.management.gateway.resources.v1_0 + + + com.sun.jersey.spi.container.ResourceFilters + com.gluster.storage.management.gateway.filters.GlusterResourceFilterFactory + + 1 + + + gluster-resources-1.0 + /1.0/* + + + JnlpDownloadServlet + jnlp.sample.servlet.JnlpDownloadServlet + + + JnlpDownloadServlet + *.jnlp + + + JnlpDownloadServlet + *.jar + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy - - - springSecurityFilterChain - /* - - - - - Gluster Management Gateway - /* - - - CONFIDENTIAL - - - + + + springSecurityFilterChain + /* + + + + Gluster Management Gateway + /* + + + CONFIDENTIAL + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/build/glusterserver.ant b/src/com.gluster.storage.management.server/build/glusterserver.ant index e9b5b650..68a5bc08 100644 --- a/src/com.gluster.storage.management.server/build/glusterserver.ant +++ b/src/com.gluster.storage.management.server/build/glusterserver.ant @@ -1,4 +1,4 @@ - + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java new file mode 100644 index 00000000..1f577c89 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java @@ -0,0 +1,118 @@ +/** + * DefaultVolumeOptions.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.gateway.constants; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +@Component +public class VolumeOptionsDefaults { + public List options; + + public VolumeOptionsDefaults() { + } + + /** + * @return list of volume option information objects + */ + public List getDefaults() { + return getVolumeOptionsInfo(); + } + + /** + * Fetches the list of all volume options with their information from GlusterFS and returns the same + * + * @return List of volume option information objects + */ + private List getVolumeOptionsInfo() { + List volumeOptionsInfo = new ArrayList(); + + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.stripe-block-size", + "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " + + CoreConstants.NEWLINE + + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern . ", + "*:128KB")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.self-heal-window-size", + "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", + "16")); + volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", + "cluster.data-self-heal-algorithm", "auto")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "network.frame-timeout", + "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", + "1800")); + volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", + "The time duration for which the client waits to check if the server is responsive.", "42")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", + "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", + "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.cache-refresh-timeout", + "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", + "1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", + "Size of the per-file write-behind buffer.", "1MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", + "performance.cache-max-file-size", "-1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", + "performance.cache-min-file-size", "0")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.io-thread-count", + " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", + "16")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "diagnostics.latency-measurement", + "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", + "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", + "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", + "Changes the log-level of the bricks (servers).", "INFO")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", + "Changes the log-level of the clients.", "INFO")); + volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", + "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", + "off")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "nfs.mem-factor", + "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", + "15")); + volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); + + return volumeOptionsInfo; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java new file mode 100644 index 00000000..3e5ea01a --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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.gateway.data; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +import org.hibernate.cfg.AnnotationConfiguration; +import org.hibernate.tool.hbm2ddl.SchemaExport; + +@Entity(name="cluster_info") +public class ClusterInfo { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @OneToMany(mappedBy="cluster") + private List servers = new ArrayList(); + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public List getServers() { + return servers; + } + + public void addServer(ServerInfo server) { + servers.add(server); + } + + public static void main(String args[]) { + AnnotationConfiguration config = new AnnotationConfiguration(); + config.addAnnotatedClass(ClusterInfo.class); + config.addAnnotatedClass(ServerInfo.class); + config.configure(); + new SchemaExport(config).create(true, true); + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java new file mode 100644 index 00000000..0802fe93 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java @@ -0,0 +1,48 @@ +/** + * GlusterDataSource.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.gateway.data; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.stereotype.Component; + +@Component +public class GlusterDataSource extends DriverManagerDataSource { + @Autowired + ServletContext servletContext; + + public GlusterDataSource() { + setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); + + setUsername("gluster"); + // TODO: change to a stronger (encrypted) password + setPassword("gluster"); + } + + public DriverManagerDataSource getDataSource() { + // Database directory = work/data relative to context root + setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); + + return this; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java new file mode 100644 index 00000000..eb7d6514 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.gateway.data; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.PersistenceUnit; +import javax.persistence.Query; + +/** + * + */ +public class PersistenceDao { + private Class type; + + private EntityManager entityManager; + + @PersistenceUnit + private EntityManagerFactory entityManagerFactory; + + public PersistenceDao(Class type) { + this.type = type; + } + + public EntityTransaction startTransaction() { + EntityTransaction txn = getEntityManager().getTransaction(); + txn.begin(); + return txn; + } + + private synchronized EntityManager getEntityManager() { + if (entityManager == null) { + entityManager = entityManagerFactory.createEntityManager(); + } + return entityManager; + } + + public Object getSingleResult(String query) { + return getEntityManager().createQuery(query).getSingleResult(); + } + + public Object getSingleResult(String queryString, String... params) { + return createQuery(queryString, params).getSingleResult(); + } + + private Query createQuery(String queryString, String... params) { + Query query = getEntityManager().createQuery(queryString); + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + return query; + } + + public Object getSingleResultFromSQL(String sqlQuery) { + return getEntityManager().createNativeQuery(sqlQuery).getSingleResult(); + } + + @SuppressWarnings("rawtypes") + public List findBySQL(String sqlQuery) { + return getEntityManager().createNativeQuery(sqlQuery).getResultList(); + } + + public T findById(int id) { + return getEntityManager().find(type, id); + } + + @SuppressWarnings("unchecked") + public List findAll() { + return getEntityManager().createQuery("select t from " + type.getName() + " t").getResultList(); + } + + @SuppressWarnings("unchecked") + public List findBy(String whereClause) { + return getEntityManager().createQuery("select t from " + type.getName() + " t where " + whereClause) + .getResultList(); + } + + @SuppressWarnings("unchecked") + public List findBy(String whereClause, String... params) { + return createQuery("select t from " + type.getName() + " t where " + whereClause, params).getResultList(); + } + + public void save(Object obj) { + getEntityManager().persist(obj); + } + + public T update(T obj) { + return getEntityManager().merge(obj); + } + + public void delete(Object obj) { + getEntityManager().remove(obj); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java new file mode 100644 index 00000000..a3f8c920 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.gateway.data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +/** + * + */ +@Entity(name="server_info") +public class ServerInfo { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @ManyToOne + @JoinColumn(name="cluster_id") + private ClusterInfo cluster; + + public ServerInfo() { + } + + public ServerInfo(String name) { + setName(name); + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setCluster(ClusterInfo cluster) { + this.cluster = cluster; + } + + public ClusterInfo getCluster() { + return cluster; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java new file mode 100644 index 00000000..31810123 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java @@ -0,0 +1,38 @@ +/** + * + */ +package com.gluster.storage.management.gateway.filters; + +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerRequestFilter; +import com.sun.jersey.spi.container.ContainerResponse; +import com.sun.jersey.spi.container.ContainerResponseFilter; +import com.sun.jersey.spi.container.ResourceFilter; + +/** + * Resource filter for maintaining audit trail of resource access + */ +public class AuditFilter implements ResourceFilter, ContainerRequestFilter, ContainerResponseFilter { + + @Override + public ContainerRequestFilter getRequestFilter() { + return this; + } + + @Override + public ContainerResponseFilter getResponseFilter() { + return this; + } + + @Override + public ContainerRequest filter(ContainerRequest req) { + System.out.println("REQUEST: [" + req.getMethod() + "][" + req.getPath() + "]"); + return req; + } + + @Override + public ContainerResponse filter(ContainerRequest req, ContainerResponse response) { + System.out.println("RESPONSE: [" + req.getMethod() + "][" + req.getPath() + "]"); + return response; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java new file mode 100644 index 00000000..73a1085e --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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.gateway.filters; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import javax.ws.rs.core.Response; + +/** + * @author root + * + */ +public class AuthenticationFailureFilter implements Filter { + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#destroy() + */ + @Override + public void destroy() { + // TODO Auto-generated method stub + + } + + public class CharResponseWrapper extends HttpServletResponseWrapper { + private CharArrayWriter output; + + public String toString() { + return output.toString(); + } + + public CharResponseWrapper(HttpServletResponse response) { + super(response); + output = new CharArrayWriter(); + } + + public PrintWriter getWriter() { + return new PrintWriter(output); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, + ServletException { + HttpServletRequest request = (HttpServletRequest) req; + if (request.getRequestURI().contains("download")) { + chain.doFilter(req, res); + return; + } + + CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) res); + chain.doFilter(req, wrapper); + + if(wrapper.getStatus() == Response.Status.UNAUTHORIZED.ordinal()) { + PrintWriter out = res.getWriter(); + out.println("1Authentication Failed!"); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + */ + @Override + public void init(FilterConfig arg0) throws ServletException { + // TODO Auto-generated method stub + + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java new file mode 100644 index 00000000..1c480f3f --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java @@ -0,0 +1,31 @@ +/** + * + */ +package com.gluster.storage.management.gateway.filters; + +import java.util.ArrayList; +import java.util.List; + +import com.sun.jersey.api.model.AbstractMethod; +import com.sun.jersey.spi.container.ResourceFilter; +import com.sun.jersey.spi.container.ResourceFilterFactory; + +/** + * Gluster resource filter factory. As of now, this creates only one filter - the audit filter {@code AuditFilter} + */ +public class GlusterResourceFilterFactory implements ResourceFilterFactory { + + public GlusterResourceFilterFactory() { + } + + /* (non-Javadoc) + * @see com.sun.jersey.spi.container.ResourceFilterFactory#create(com.sun.jersey.api.model.AbstractMethod) + */ + @Override + public List create(AbstractMethod arg0) { + List filters = new ArrayList(); + filters.add(new AuditFilter()); + + return filters; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java new file mode 100644 index 00000000..9fc4fceb --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; + +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +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 + * 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(); + } + + protected StreamingOutput createStreamingOutput(final byte[] data) { + return new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException { + output.write(data); + } + }; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java new file mode 100644 index 00000000..d0da6696 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * 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.gateway.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.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.response.ClusterNameListResponse; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.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; + private static final Logger logger = Logger.getLogger(ClustersResource.class); + + @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()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); + } + + clusterService.createCluster(clusterName); + return createdResponse(clusterName); + } + + @PUT + public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { + if(clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(knownServer == null || knownServer.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); + } + + ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); + if(mappedCluster != null) { + throw new GlusterValidationException("Server [" + knownServer + "] is already present in cluster [" + + mappedCluster.getName() + "]!"); + } + + clusterService.registerCluster(clusterName, knownServer); + return noContentResponse(clusterName); + } + + @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") + @DELETE + public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + if(clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if(cluster == null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] does not exist!"); + } + + clusterService.unregisterCluster(cluster); + return noContentResponse(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java new file mode 100644 index 00000000..2d07bd24 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * 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.gateway.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.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_DISCOVERED_SERVERS) +public class DiscoveredServersResource extends AbstractResource { + @InjectParam + protected ServerUtil serverUtil; + + @InjectParam + protected GlusterUtil glusterUtil; + + 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/gateway/resources/v1_0/GenericExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java new file mode 100644 index 00000000..3a316c0c --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; + +@Provider +public class GenericExceptionMapper implements ExceptionMapper { + + /* (non-Javadoc) + * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) + */ + @Override + public Response toResponse(Exception exception) { + ResponseBuilder builder; + if (exception instanceof GlusterValidationException) { + builder = Response.status(Response.Status.BAD_REQUEST); + } else { + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); + } + + String errMsg = exception.getMessage(); + if(errMsg == null) { + errMsg = "Following exception occurred : " + exception.getClass().getName(); + StackTraceElement[] stackTrace = exception.getStackTrace(); + if(stackTrace.length > 0) { + errMsg += " at [" + stackTrace[0].getClassName() + "][" + stackTrace[0].getLineNumber() + "]"; + } + } + return builder.entity(errMsg).type(MediaType.TEXT_PLAIN).build(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java new file mode 100644 index 00000000..e6e4f9d6 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java @@ -0,0 +1,487 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE; +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.QUERY_PARAM_DETAILS; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_INTERFACE; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_PERIOD; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; +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_STATISTICS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK; + +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.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.response.GlusterServerListResponse; +import com.gluster.storage.management.core.response.ServerNameListResponse; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.services.GlusterServerService; +import com.gluster.storage.management.gateway.tasks.InitializeDiskTask; +import com.gluster.storage.management.gateway.utils.CpuStatsFactory; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.MemoryStatsFactory; +import com.gluster.storage.management.gateway.utils.NetworkStatsFactory; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.gluster.storage.management.gateway.utils.StatsFactory; +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 AbstractResource { + + public static final String HOSTNAMETAG = "hostname:"; + + @InjectParam + private DiscoveredServersResource discoveredServersResource; + + @InjectParam + private TasksResource taskResource; + + @InjectParam + private ClusterService clusterService; + + @InjectParam + private SshUtil sshUtil; + + @InjectParam + private CpuStatsFactory cpuStatsFactory; + + @InjectParam + private MemoryStatsFactory memoryStatsFactory; + + @InjectParam + private NetworkStatsFactory networkStatsFactory; + + @InjectParam + private ServerUtil serverUtil; + + @InjectParam + private GlusterUtil glusterUtil; + + @InjectParam + private GlusterServerService glusterServerService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); + } + + private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { + if(fetchDetails == null) { + // by default, fetch the server details + fetchDetails = true; + } + + 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); + } + + try { + glusterServers = glusterServerService.getGlusterServers(clusterName, fetchDetails); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + + if(fetchDetails) { + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } else { + // no details to be fetched. Return list of server names. + return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType); + } + } + + private List getServerNames(List glusterServers) { + List serverNames = new ArrayList(); + for(GlusterServer server : glusterServers) { + serverNames.add(server.getName()); + } + return serverNames; + } + + @GET + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + @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("{" + PATH_PARAM_SERVER_NAME + "}") + @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(glusterServerService.getGlusterServer(clusterName, serverName, true), mediaType); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + 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."); + } + + String hostName = serverUtil.fetchHostName(serverName); + 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, hostName); + } 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()); + } + } + clusterService.unmapServerFromCluster(clusterName, serverName); + + 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); + } + + // 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, + @FormParam(FORM_PARAM_FSTYPE) String fsType) { + + 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!"); + } + + if (fsType == null || fsType.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_FSTYPE + "] is missing in request!"); + } + + InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName, fsType); + try { + initializeTask.start(); + // Check the initialize disk status + TaskStatus taskStatus = initializeTask.checkStatus(); + initializeTask.getTaskInfo().setStatus(taskStatus); + taskResource.addTask(initializeTask); + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + @GET + @Produces(MediaType.APPLICATION_XML) + @Path(RESOURCE_STATISTICS) + public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_XML); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path(RESOURCE_STATISTICS) + public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_JSON); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_XML); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_JSON); + } + + private Response getAggregaredPerformanceData(String clusterName, String type, String period, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (cluster.getServers().isEmpty()) { + // cluster is empty. return empty stats. + return okResponse(new ServerStats(), mediaType); + } + + List serverNames = getServerNames(glusterServerService.getGlusterServers(clusterName, false)); + return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); + } + + private Response getPerformanceData(String clusterName, String serverName, String type, String period, String networkInterface, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterValidationException("Server name must not be empty!"); + } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + + return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); + } + + private StatsFactory getStatsFactory(String type) { + if(type.equals(STATISTICS_TYPE_CPU)) { + return cpuStatsFactory; + } else if(type.equals(STATISTICS_TYPE_MEMORY)) { + return memoryStatsFactory; + } else if(type.equals(STATISTICS_TYPE_NETWORK)) { + return networkStatsFactory; + } else { + throw new GlusterValidationException("Invalid server statistics type [" + type + "]. Valid values are [" + + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java new file mode 100644 index 00000000..34dad497 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java @@ -0,0 +1,153 @@ +/** + * KeysResource.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.gateway.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_KEYS; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +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.utils.FileUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.multipart.FormDataParam; + +@Path(RESOURCE_PATH_KEYS) +public class KeysResource extends AbstractResource { + private static final Logger logger = Logger.getLogger(KeysResource.class); + private ProcessUtil processUtil = new ProcessUtil(); + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response exportSshkeys() { + File archiveFile = new File(createSskKeyZipFile()); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); + } + + private String createSskKeyZipFile() { + String targetDir = System.getProperty("java.io.tmpdir"); + String zipFile = targetDir + "ssh-keys.tar"; + String sourcePemFile = SshUtil.PRIVATE_KEY_FILE.getAbsolutePath(); + String sourcePubKeyFile = SshUtil.PUBLIC_KEY_FILE.getAbsolutePath(); + String targetPemFile = targetDir + File.separator + SshUtil.PRIVATE_KEY_FILE.getName(); + String targetPubKeyFile = targetDir + File.separator + SshUtil.PUBLIC_KEY_FILE.getName(); + + if (!SshUtil.PRIVATE_KEY_FILE.isFile()) { + throw new GlusterRuntimeException("No private key file [" + SshUtil.PRIVATE_KEY_FILE.getName() + "] found!" ); + } + + if (!SshUtil.PUBLIC_KEY_FILE.isFile()) { + throw new GlusterRuntimeException("No public key file [" + SshUtil.PUBLIC_KEY_FILE.getName() + "] found!" ); + } + + // Copy keys to temp folder + ProcessResult result = processUtil.executeCommand("cp", sourcePemFile, targetPemFile); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); + } + result = processUtil.executeCommand("cp", sourcePubKeyFile, targetPubKeyFile); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); + } + + // To compress the key files + result = processUtil.executeCommand("tar", "cvf", zipFile, "-C", "/tmp", SshUtil.PRIVATE_KEY_FILE.getName(), + SshUtil.PUBLIC_KEY_FILE.getName()); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to compress key files! [" + result.getOutput() + "]"); + } + + // To remove the copied key files + try { + processUtil.executeCommand("rm", "-f", targetPemFile, targetPubKeyFile); // Ignore the errors if any + } catch (Exception e) { + logger.warn(e.toString()); + } + return zipFile; + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response importSshKeys(@FormDataParam("file") InputStream uploadedInputStream) { + File uploadedFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "keys.tar"); + String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + + writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); + + // To backup existing SSH pem and public keys, if exist. + if (SshUtil.PRIVATE_KEY_FILE.isFile()) { + if (!SshUtil.PRIVATE_KEY_FILE.renameTo(new File(SshUtil.PRIVATE_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup pem key!"); + } + } + + if (SshUtil.PUBLIC_KEY_FILE.isFile()) { + if (!SshUtil.PUBLIC_KEY_FILE + .renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup public key!"); + } + } + // Extract SSH pem and public key files. + ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", + SshUtil.SSH_AUTHORIZED_KEYS_DIR_LOCAL); + uploadedFile.delete(); + if (!output.isSuccess()) { + throw new GlusterRuntimeException(output.getOutput()); + } + return createdResponse("SSH Key imported successfully"); + } + + // save uploaded file to the file (with path) + private void writeToFile(InputStream inputStream, String toFile) { + try { + int read = 0; + byte[] bytes = new byte[1024]; + + OutputStream out = new FileOutputStream(new File(toFile)); + while ((read = inputStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + out.flush(); + out.close(); + } catch (IOException e) { + throw new GlusterRuntimeException(e.getMessage()); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java new file mode 100644 index 00000000..e5874f4b --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java @@ -0,0 +1,194 @@ +/** + * 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.gateway.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 org.springframework.stereotype.Component; + +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.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.response.TaskInfoListResponse; +import com.gluster.storage.management.gateway.tasks.Task; +import com.sun.jersey.spi.resource.Singleton; + +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) +@Singleton +@Component +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; + } + + public List getAllTasks() { + List tasks = new ArrayList(); + for (Map.Entry entry : tasksMap.entrySet()) { + checkTaskStatus(entry.getKey()); + tasks.add( (Task) entry.getValue()); + } + return tasks; + } + + @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); + // No status check required if the task already complete or failure + if (task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_FAILURE + || task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + return task; + } + 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(); + clearTask(taskId, taskOperation); // Stop and remove from the task list + } 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 clearTask(@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/gateway/resources/v1_0/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java new file mode 100644 index 00000000..4b2701f2 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/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.gateway.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/gateway/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java new file mode 100644 index 00000000..fad19e7e --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java @@ -0,0 +1,988 @@ +/** + * 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.gateway.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.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.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.log4j.Logger; + +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.gateway.constants.VolumeOptionsDefaults; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.tasks.MigrateBrickTask; +import com.gluster.storage.management.gateway.tasks.RebalanceVolumeTask; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.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"; + private static final Logger logger = Logger.getLogger(VolumesResource.class); + + @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) { + Status status; + try { + status = 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 + "]"); + } + status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } + if (!status.isSuccess()) { + throw new GlusterRuntimeException(status.toString()); + } + } + + @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); + File archiveFile = new File(downloadLogs(volume)); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); + } catch (Exception e) { + logger.error("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]! [" + + e.getStackTrace() + "]"); + throw (GlusterRuntimeException) e; + } + } + + + 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 getLayout(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 layout; + } + + private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, + Boolean isForcedDataMigrate) { + RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName, getLayout( + isFixLayout, isMigrateData, isForcedDataMigrate)); + 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(); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java new file mode 100644 index 00000000..e806051c --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java @@ -0,0 +1,31 @@ +/** + * GlusterUserDetailsService.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.gateway.security; + +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * + */ +public interface GlusterUserDetailsService extends UserDetailsService { + void changePassword(String username, String password); +} + diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java new file mode 100644 index 00000000..bdc3b19e --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java @@ -0,0 +1,42 @@ +/** + * UserAuthDao.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.gateway.security; + +import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; + +/** + * @author root + * + */ +public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.gateway.security.GlusterUserDetailsService#changePassword(java.lang.String, + * java.lang.String) + */ + @Override + public void changePassword(String username, String password) { + getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java new file mode 100644 index 00000000..e01c5096 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * 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.gateway.services; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityTransaction; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.utils.LRUCache; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; + +/** + * Service class for functionality related to clusters + */ +@Component +public class ClusterService { + @Autowired + private PersistenceDao clusterDao; + + @Autowired + private PersistenceDao serverDao; + + @Autowired + private GlusterUtil glusterUtil; + + @Autowired + private SshUtil sshUtil; + + @Autowired + private ServerUtil serverUtil; + + private LRUCache onlineServerCache = new LRUCache(3); + + private static final Logger logger = Logger.getLogger(ClusterService.class); + + public void addOnlineServer(String clusterName, GlusterServer server) { + onlineServerCache.put(clusterName, server); + } + + public void removeOnlineServer(String clusterName) { + onlineServerCache.remove(clusterName); + } + + // uses cache + public GlusterServer getOnlineServer(String clusterName, String exceptServerName) { + GlusterServer server = onlineServerCache.get(clusterName); + if (server != null && !server.getName().equals(exceptServerName)) { + return server; + } + + return getNewOnlineServer(clusterName, exceptServerName); + } + + public GlusterServer getNewOnlineServer(String clusterName) { + return getNewOnlineServer(clusterName, ""); + } + + public GlusterServer getOnlineServer(String clusterName) { + return getOnlineServer(clusterName, ""); + } + + // Doesn't use cache + public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) { + ClusterInfo cluster = getCluster(clusterName); + if (cluster == null) { + throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!"); + } + + for (ServerInfo serverInfo : cluster.getServers()) { + GlusterServer server = new GlusterServer(serverInfo.getName()); + try { + serverUtil.fetchServerDetails(server); // Online status come with server details + // server is online. add it to cache and return + if (server.isOnline() && !server.getName().equals(exceptServerName)) { + addOnlineServer(clusterName, server); + return server; + } + } catch (ConnectionException e) { + // server is offline. continue checking next one. + continue; + } + } + + // no online server found. + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + public List getAllClusters() { + return clusterDao.findAll(); + } + + public ClusterInfo getCluster(String clusterName) { + List clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase()); + if(clusters.size() == 0) { + return null; + } + + return clusters.get(0); + } + + public ClusterInfo getClusterForServer(String serverName) { + List servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase()); + if(servers.size() == 0) { + return null; + } + + return servers.get(0).getCluster(); + } + + public void createCluster(String clusterName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + try { + clusterDao.save(cluster); + txn.commit(); + } catch (RuntimeException e) { + txn.rollback(); + logger.error("Exception while trying to save cluster [" + clusterName + "] : [" + e.getMessage() + "]", e); + throw e; + } + } + + public void registerCluster(String clusterName, String knownServer) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + GlusterServer server = new GlusterServer(knownServer); + try { + List glusterServers = glusterUtil.getGlusterServers(server); + List servers = new ArrayList(); + 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) { + logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); + txn.rollback(); + logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); + 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(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 { + for(ServerInfo server : cluster.getServers()) { + clusterDao.delete(server); + } + cluster.getServers().clear(); + clusterDao.update(cluster); + clusterDao.delete(cluster); + txn.commit(); + } catch (RuntimeException e) { + logger.error("Error in unregistering cluster [" + cluster.getName() + "] : " + e.getMessage(), e); + txn.rollback(); + throw e; + } + } + + public void mapServerToCluster(String clusterName, String serverName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = getCluster(clusterName); + ServerInfo server = new ServerInfo(serverName); + server.setCluster(cluster); + try { + clusterDao.save(server); + cluster.addServer(server); + clusterDao.update(cluster); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + throw new GlusterRuntimeException("Couldn't create cluster-server mapping [" + clusterName + "][" + + serverName + "]! Error: " + e.getMessage(), e); + } + } + + public void unmapServerFromCluster(String clusterName, String serverName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = getCluster(clusterName); + List servers = cluster.getServers(); + for(ServerInfo server : servers) { + if(server.getName().equals(serverName)) { + servers.remove(server); + clusterDao.delete(server); + break; + } + } + try { + clusterDao.update(cluster); + txn.commit(); + } catch(Exception e) { + txn.rollback(); + throw new GlusterRuntimeException("Couldn't unmap server [" + serverName + "] from cluster [" + clusterName + + "]! Error: " + e.getMessage(), e); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java new file mode 100644 index 00000000..d1437cec --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.gateway.services; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; + +/** + * + */ +@Component +public class GlusterServerService { + @Autowired + protected ServerUtil serverUtil; + + @Autowired + private ClusterService clusterService; + + @Autowired + private GlusterUtil glusterUtil; + + public void fetchServerDetails(GlusterServer server) { + try { + server.setStatus(SERVER_STATUS.ONLINE); + serverUtil.fetchServerDetails(server); + } catch (ConnectionException e) { + server.setStatus(SERVER_STATUS.OFFLINE); + } + } + + public List getGlusterServers(String clusterName, boolean fetchDetails) { + List glusterServers; + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); + } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); + } + return glusterServers; + } + + private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { + 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); + } + + if (fetchDetails) { + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); + } + } + return glusterServers; + } + + private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { + String errMsg = ""; + + for (GlusterServer server : glusterServers) { + try { + fetchServerDetails(server); + } catch (Exception e) { + errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; + } + } + return errMsg; + } + + public GlusterServer getGlusterServer(String clusterName, String serverName, Boolean fetchDetails) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterValidationException("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 + "]"); + } + + return getGlusterServer(clusterName, serverName, onlineServer, fetchDetails); + } + + private GlusterServer getGlusterServer(String clusterName, String serverName, GlusterServer onlineServer, + Boolean fetchDetails) { + 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 (fetchDetails && server.isOnline()) { + fetchServerDetails(server); + } + return server; + } + + public boolean isValidServer(String clusterName, String serverName) { + try { + GlusterServer server = getGlusterServer(clusterName, serverName, false); + return server != null; + } catch(Exception e) { + return false; + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java new file mode 100644 index 00000000..6d525785 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java @@ -0,0 +1,162 @@ +/** + * GlusterServerInitializer.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.gateway.tasks; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.apache.derby.tools.ij; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.security.authentication.encoding.PasswordEncoder; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; + +/** + * Initializes the Gluster Management Server. + */ +public class InitServerTask extends JdbcDaoSupport { + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private String appVersion; + + @Autowired + private PersistenceDao clusterDao; + + @Autowired + ServletContext servletContext; + + private static final String SCRIPT_DIR = "data/scripts/"; + + public void securePasswords() { + getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + String username = rs.getString(1); + String password = rs.getString(2); + String encodedPassword = passwordEncoder.encodePassword(password, null); + getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); + logger.debug("Updating password for username: " + username); + } + }); + } + + private void executeScript(File script) { + ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); + int numOfExceptions; + try { + numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), new FileInputStream( + script), CoreConstants.ENCODING_UTF8, sqlOut, CoreConstants.ENCODING_UTF8); + String output = sqlOut.toString(); + sqlOut.close(); + logger.debug("Data script [" + script.getName() + "] returned with exit status [" + numOfExceptions + + "] and output [" + output + "]"); + if (numOfExceptions != 0) { + throw new GlusterRuntimeException("Server data initialization script [ " + script.getName() + + "] failed with [" + numOfExceptions + "] exceptions! [" + output + "]"); + } + } catch (Exception ex) { + throw new GlusterRuntimeException("Server data initialization script [" + script.getName() + "] failed!", + ex); + } + } + + private void initDatabase() { + logger.info("Initializing server data..."); + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + appVersion)); + + securePasswords(); // encrypt the passwords + } + + private File getDirFromRelativePath(String relativePath) { + String scriptDirPath = servletContext.getRealPath(relativePath); + File scriptDir = new File(scriptDirPath); + return scriptDir; + } + + private void executeScriptsFrom(File scriptDir) { + if (!scriptDir.exists()) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] doesn't exist!"); + } + + List scripts = Arrays.asList(scriptDir.listFiles()); + if(scripts.size() == 0) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] is empty!"); + } + + Collections.sort(scripts); + for (File script : scripts) { + executeScript(script); + } + } + + /** + * Initializes the server database, if running for the first time. + */ + public synchronized void initServer() { + try { + String dbVersion = getDBVersion(); + if (!appVersion.equals(dbVersion)) { + logger.info("App version [" + appVersion + "] differs from data version [" + dbVersion + + "]. Trying to upgrade data..."); + upgradeData(dbVersion, appVersion); + } + } catch (Exception ex) { + logger.info("No cluster created yet. DB version query failed with error [" + ex.getMessage() + "]", ex); + // Database not created yet. Create it! + initDatabase(); + } + + // For development time debugging. To be removed later. + List clusters = clusterDao.findAll(); + logger.info(clusters.size()); + + if (clusters.size() > 0) { + for (ClusterInfo cluster : clusters) { + logger.info("Cluster: [" + cluster.getId() + "][" + cluster.getName() + "]"); + } + } else { + + } + } + + private void upgradeData(String fromVersion, String toVersion) { + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + fromVersion + "-" + toVersion)); + } + + private String getDBVersion() { + return (String) clusterDao.getSingleResultFromSQL("select version from version"); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java new file mode 100644 index 00000000..f5cc5332 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java @@ -0,0 +1,168 @@ +/** + * InitializeDiskTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.core.util.Base64; + +public class InitializeDiskTask extends Task { + + private static final String INITIALIZE_DISK_SCRIPT = "format_device.py"; + + private String serverName; + private String diskName; + private String fsType; + private SshUtil sshUtil; + private GlusterUtil glusterUtil; + + public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, String fsType) { + super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" + + diskName, false, false, false); + + setServerName(serverName); + setDiskName(diskName); + setFsType(fsType); + taskInfo.setName(getId()); + init(); + } + + public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { + super(clusterService, clusterName, info); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + glusterUtil = ctx.getBean(GlusterUtil.class); + sshUtil = ctx.getBean(SshUtil.class); + } + + @Override + public String getId() { + return new String( + Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void stop() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } + + @Override + public TASK_TYPE getType() { + return TASK_TYPE.DISK_FORMAT; + } + + + @Override + public void start() { + try { + startInitializeDisk(serverName); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } + } + + private void startInitializeDisk(String serverName) { + String fsTypeCommand = (getFsType().equals(GlusterConstants.FSTYPE_DEFAULT)) ? "" : " -t " + getFsType(); + ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_SCRIPT + fsTypeCommand + " " + + getDiskName()); + if (processResult.isSuccess()) { + TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput())); + taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); + getTaskInfo().setStatus(taskStatus); + return; + } + + // if we reach here, it means Initialize disk start failed. + throw new GlusterRuntimeException(processResult.toString()); + } + + @Override + public TaskStatus checkStatus() { + + try { + return glusterUtil.getInitializingDeviceStatus(serverName, getDiskName()); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); + } + } + + public void setDiskName(String diskName) { + this.diskName = diskName; + } + + public String getDiskName() { + return diskName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getServerName() { + return serverName; + } + + public void setFsType(String fsType) { + this.fsType = fsType; + } + + public String getFsType() { + return fsType; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java new file mode 100644 index 00000000..694067aa --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java @@ -0,0 +1,227 @@ +/** + * MigrateDiskTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.sun.jersey.core.util.Base64; + +public class MigrateBrickTask extends Task { + + private String fromBrick; + private String toBrick; + private Boolean autoCommit; + private GlusterUtil glusterUtil; + + public String getFromBrick() { + return fromBrick; + } + + public void setFromBrick(String fromBrick) { + this.fromBrick = fromBrick; + } + + public String getToBrick() { + return toBrick; + } + + public void setToBrick(String toBrick) { + this.toBrick = toBrick; + } + + public Boolean getAutoCommit() { + return autoCommit; + } + + public void setAutoCommit(Boolean autoCommit) { + this.autoCommit = autoCommit; + } + + public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, + String toBrick) { + super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" + + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); + setFromBrick(fromBrick); + setToBrick(toBrick); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + glusterUtil = ctx.getBean(GlusterUtil.class); + } + + @Override + public String getId() { + return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + + toBrick)); + } + + @Override + public void start() { + try { + startMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone Offline. try with a new one. + startMigration(getNewOnlineServer().getName()); + } + } + + private void startMigration(String onlineServerName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServerName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "start"); + if (processResult.getOutput().trim().matches(".*started successfully$")) { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); + return; + } + } + + @Override + public void pause() { + try { + pauseMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + pauseMigration(getNewOnlineServer().getName()); + } + } + + private void pauseMigration(String onlineServer) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServer, taskInfo.getReference(), + getFromBrick(), getToBrick(), "pause"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*paused successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_PAUSE); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + return; + } + } + + @Override + public void resume() { + start(); + } + + @Override + public void commit() { + try { + commitMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + commitMigration(getNewOnlineServer().getName()); + } + } + + private void commitMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "commit"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches(".*commit successful$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + } + } + } + + @Override + public void stop() { + try { + stopMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + stopMigration(getNewOnlineServer().getName()); + } + } + + private void stopMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, taskInfo.getReference(), getFromBrick(), + getToBrick(), "abort"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*aborted successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + } + } + + @Override + public TaskStatus checkStatus() { + try { + return checkMigrationStatus(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + return checkMigrationStatus(getNewOnlineServer().getName()); + } + } + + private TaskStatus checkMigrationStatus(String serverName) { + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE) { + return getTaskInfo().getStatus(); + } + // For committed task, status command (CLI) is invalid, just return current status + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + return getTaskInfo().getStatus(); + } + + + TaskStatus taskStatus = new TaskStatus(); + try { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "status"); + if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$") + || processResult.getOutput().trim().matches("^Number of files migrated = 0 .*Current file=")) { + // Note: Workaround - if no file in the volume brick to migrate, Gluster CLI is not giving proper + // (complete) status + taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); + if (autoCommit) { + commitMigration(serverName); + return getTaskInfo().getStatus(); // return the committed status + } else { + taskStatus.setMessage(processResult.getOutput().trim() + .replaceAll("Migration complete", "Commit pending")); + } + } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); + } catch (Exception e) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(e.getMessage()); + } + taskInfo.setStatus(taskStatus); // Update the task status + return taskStatus; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java new file mode 100644 index 00000000..3038f961 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java @@ -0,0 +1,134 @@ +/** + * RebalanceVolumeTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.core.util.Base64; + +public class RebalanceVolumeTask extends Task { + + private String layout; + private String serverName; + private SshUtil sshUtil; + private GlusterUtil glusterUtil; + + public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { + super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName + + " Rebalance", false, true, false); + setLayout(layout); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + sshUtil = ctx.getBean(SshUtil.class); + glusterUtil = ctx.getBean(GlusterUtil.class); + } + + @Override + public String getId() { + return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); + } + + @Override + public void start() { + try { + serverName = getOnlineServer().getName(); + startRebalance(serverName); + } catch(ConnectionException e) { + // online server might have gone offline. try with a new one + serverName = getNewOnlineServer().getName(); + startRebalance(serverName); + } + } + + private void startRebalance(String serverName) { + String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + if (processResult.isSuccess()) { + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); + return; + } + + // if we reach here, it means rebalance start failed. + throw new GlusterRuntimeException(processResult.toString()); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public void stop() { + try { + glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); + } catch (ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public TaskStatus checkStatus() { + try { + return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + return getTaskInfo().getStatus(); + } + } + + public void setLayout(String layout) { + this.layout = layout; + } + + public String getLayout() { + return layout; + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java new file mode 100644 index 00000000..94c743aa --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java @@ -0,0 +1,154 @@ +/** + * ServerDiscoveryTask.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.gateway.tasks; + +import java.util.ArrayList; +import java.util.List; + +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.GlusterConstants; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.resources.v1_0.DiscoveredServersResource; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.services.GlusterServerService; +import com.gluster.storage.management.gateway.utils.ServerUtil; + +/** + * Task for syncing server details. This performs two things:
+ * 1. Auto-discovery of servers eligible to be added to the Gluster cluster.
+ * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user + * adds/removes servers manually using the CLI. + */ +@Component +public class ServerSyncTask { + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private DiscoveredServersResource discoveredServersResource; + + @Autowired + private GlusterServerService glusterServerService; + + @Autowired + private String discoveryMechanism; + + @Autowired + private ClusterService clusterService; + + @Autowired + private PersistenceDao clusterDao; + + public void perform() { + discoverServers(); + syncClusterServerMapping(); + } + + private void syncClusterServerMapping() { + List clusters = clusterService.getAllClusters(); + for(ClusterInfo cluster : clusters) { + List servers = cluster.getServers(); + List actualServers = glusterServerService.getGlusterServers(cluster.getName(), false); + updateRemovedServers(cluster, servers, actualServers); + updateAddedServers(cluster, servers, actualServers); + } + } + + private void updateAddedServers(ClusterInfo cluster, List servers, List actualServers) { + List addedServers = findAddedServers(cluster.getName(), servers, actualServers); + for(String addedServer : addedServers) { + clusterService.mapServerToCluster(cluster.getName(), addedServer); + } + } + + private void updateRemovedServers(ClusterInfo cluster, List servers, List actualServers) { + List removedServers = findRemovedServers(servers, actualServers); + for(String removedServer : removedServers) { + clusterService.unmapServerFromCluster(cluster.getName(), removedServer); + } + } + + private List findRemovedServers(List servers, List actualServers) { + List removedServers = new ArrayList(); + + for(ServerInfo server : servers) { + if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { + removedServers.add(server.getName()); + } + } + return removedServers; + } + + private List findAddedServers(String clusterName, List servers, List actualServers) { + List addedServers = new ArrayList(); + for(GlusterServer actualServer : actualServers) { + if(!serverExists(servers, actualServer.getName())) { + addedServers.add(actualServer.getName()); + } + } + return addedServers; + } + + private boolean serverExists(List servers, String name) { + for(ServerInfo server : servers) { + if(server.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private void discoverServers() { + if(discoveryMechanism.equals(GlusterConstants.NONE)) { + return; + } + + List serverNameList = new ArrayList(); + + ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList()); + if(result.isSuccess()) { + List existingServers = clusterDao.findBySQL("select name from server_info"); + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + for(String serverName : parts) { + // The server discovery mechanism will return every server that has not been "peer probed". However we + // need to filter out those servers that are the "first" server of a new cluster, and hence are still + // not peer probed. + if(!existingServers.contains(serverName)) { + serverNameList.add(serverName); + } + } + } + + discoveredServersResource.setDiscoveredServerNames(serverNameList); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java new file mode 100644 index 00000000..1ba360bc --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java @@ -0,0 +1,112 @@ +/** + * Task.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.gateway.tasks; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.gateway.services.ClusterService; + +public abstract class Task { + public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; + + protected TaskInfo taskInfo; + protected String clusterName; + private ClusterService clusterService; + + public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, + boolean canPause, boolean canStop, boolean canCommit) { + TaskInfo taskInfo = new TaskInfo(); + taskInfo.setType(type); + taskInfo.setReference(reference); + taskInfo.setDescription(desc); + taskInfo.setPauseSupported(canPause); + taskInfo.setStopSupported(canStop); + taskInfo.setCommitSupported(canCommit); + + init(clusterService, clusterName, taskInfo); + + } + + public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + init(clusterService, clusterName, taskInfo); + } + + private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + this.clusterService = clusterService; + setClusterName(clusterName); + setTaskInfo(taskInfo); + } + + protected GlusterServer getOnlineServer() { + return clusterService.getOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer() { + return clusterService.getNewOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer(String exceptServerName) { + return clusterService.getNewOnlineServer(clusterName, exceptServerName); + } + + public String getTypeStr() { + return TASK_TYPE_STR[taskInfo.getType().ordinal()]; + } + + public TASK_TYPE getType() { + return getTaskInfo().getType(); + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public TaskInfo getTaskInfo() { + return taskInfo; + } + + public void setTaskInfo(TaskInfo info) { + this.taskInfo = info; + } + + public abstract String getId(); + + public abstract void start(); + + public abstract void resume(); + + public abstract void stop(); + + public abstract void pause(); + + public abstract void commit(); + + /** + * This method should check current status of the task and update it's taskInfo accordingly + */ + public abstract TaskStatus checkStatus(); +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java new file mode 100644 index 00000000..0e73297f --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.Status; + +/** + * + */ +@Component +public abstract class AbstractStatsFactory implements StatsFactory { + @Autowired + protected ServerUtil serverUtil; + + private Logger logger = Logger.getLogger(AbstractStatsFactory.class); + + protected ServerStats getFirstOnlineServerStats(List serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + try { + ServerStats stats = fetchStats(serverName, period); + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return stats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + int rowCount = aggregatedStats.getMetadata().getRowCount(); + int columnCount = aggregatedStats.getMetadata().getLegend().size(); + int[][] dataCount = initDataCountArray(rowCount, columnCount); + + for (String serverName : serverNames) { + try { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch performance stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + /** + * + * @param statsToBeAdded + * @param targetStats + * @param dataCount Each element of this matrix will be incremented for every valid element added + * @return + */ + protected List addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { + List serverStatsRows = statsToBeAdded.getRows(); + for (int rowNum = 0; rowNum < serverStatsRows.size() + && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { + ServerStatsRow row = serverStatsRows.get(rowNum); + List rowData = row.getUsageData(); + + List aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); + for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { + // Add the data + Double data = rowData.get(i); + if(!data.isNaN()) { + // data is available. add it. + aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); + // increment record count. this will be used for calculating average of aggregated data. + dataCount[rowNum][i]++; + } + } + } + return serverStatsRows; + } + + protected void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { + List rows = aggregatedStats.getRows(); + for(int rowNum = 0; rowNum < rows.size(); rowNum++) { + List data = rows.get(rowNum).getUsageData(); + for(int columnNum = 0; columnNum < data.size(); columnNum++) { + data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); + } + } + } + + protected int[][] initDataCountArray(int rowCount, int columnCount) { + int[][] dataCount = new int[rowCount][columnCount]; + // initialize all data counts to 1 + for(int rowNum = 0; rowNum < rowCount; rowNum++) { + for(int columnNum = 0; columnNum < columnCount; columnNum++) { + dataCount[rowNum][columnNum] = 1; + } + } + return dataCount; + } + + @Override + public ServerStats fetchAggregatedStats(List serverNames, String period) { + if(serverNames == null || serverNames.size() == 0) { + throw new GlusterRuntimeException("No server names passed to fetchAggregaredStats!"); + } + + ServerStats firstServerStats = getFirstOnlineServerStats(serverNames, period, true, true); + + ServerStats aggregatedStats = new ServerStats(firstServerStats); + aggregateStats(serverNames, aggregatedStats, period); + return aggregatedStats; + } + + @Override + public ServerStats fetchStats(String serverName, String period, String...args) { + String argsStr = ""; + for (String arg : args) { + if(arg != null) { + argsStr += " " + arg; + } + } + Object output = serverUtil.executeOnServer(true, serverName, getStatsScriptName() + argsStr + " " + period, ServerStats.class); + //String cpuUsageData = " 1310468100 300 1310471700 13 3 user system total 13104681002.23802952e-14.3747778209e-016.6128073384e-01 13104684002.3387347338e-014.4642717442e-016.8030064780e-01 13104687005.5043873220e+006.2462376636e+001.1750624986e+01 13104690002.4350593653e+012.6214585217e+015.0565178869e+01 13104693004.0786489953e+014.6784713828e+018.7571203781e+01 13104696004.1459955508e+015.2546309044e+019.4006264551e+01 13104699004.2312286165e+015.2390588332e+019.4702874497e+01 13104702004.2603794982e+015.1598861493e+019.4202656475e+01 13104705003.8238751290e+014.5312089966e+018.3550841256e+01 13104708001.7949961224e+012.1282058418e+013.9232019642e+01 13104711001.2330371421e-014.6347832868e-015.8678204289e-01 13104714001.6313260492e-015.4088119561e-017.0401380052e-01 1310471700NaNNaNNaN "; + //Object output = unmarshal(ServerStats.class, cpuUsageData, false); + if(output instanceof Status) { + throw new GlusterRuntimeException(((Status)output).toString()); + } + return (ServerStats) output; + } + + public abstract String getStatsScriptName(); +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java new file mode 100644 index 00000000..b6ef9ef2 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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.gateway.utils; + +import org.springframework.stereotype.Component; + +/** + * + */ +@Component +public class CpuStatsFactory extends AbstractStatsFactory { + + private static final String CPU_STATS_SCRIPT = "get_rrd_cpu_details.py"; + + @Override + public String getStatsScriptName() { + return CPU_STATS_SCRIPT; + } + +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java new file mode 100644 index 00000000..7622d283 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java @@ -0,0 +1,664 @@ +/** + * GlusterUtil.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.gateway.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +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.GlusterConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.InitDiskStatusResponse; +import com.gluster.storage.management.core.model.InitDiskStatusResponse.FORMAT_STATUS; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.StringUtil; +import com.gluster.storage.management.gateway.resources.v1_0.TasksResource; +import com.sun.jersey.api.core.InjectParam; + +@Component +public class GlusterUtil { + private static final String glusterFSminVersion = "3.1"; + + private static final String HOSTNAME_PFX = "Hostname:"; + private static final String UUID_PFX = "Uuid:"; + private static final String STATE_PFX = "State:"; + private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; + + private static final String VOLUME_NAME_PFX = "Volume Name:"; + private static final String VOLUME_TYPE_PFX = "Type:"; + private static final String VOLUME_STATUS_PFX = "Status:"; + private static final String VOLUME_NUMBER_OF_BRICKS = "Number of Bricks:"; + private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; + private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; + private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; + private static final String VOLUME_OPTION_AUTH_ALLOW_PFX = "auth.allow:"; + private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; + private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; + private static final String VOLUME_TYPE_REPLICATE = "Replicate"; + private static final String GLUSTERD_INFO_FILE = "/etc/glusterd/glusterd.info"; + + private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); + + private static final String INITIALIZE_DISK_STATUS_SCRIPT = "get_format_device_status.py"; + + @Autowired + private SshUtil sshUtil; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private TasksResource taskResource; + + public void setSshUtil(SshUtil sshUtil) { + this.sshUtil = sshUtil; + } + + public SshUtil getSshUtil() { + return sshUtil; + } + + /** + * Extract value of given token from given line. It is assumed that the token, if present, will be of the following + * form: token: value + * + * @param line + * Line to be analyzed + * @param token + * Token whose value is to be extracted + * @return Value of the token, if present in the line + */ + private final String extractToken(String line, String token) { + if (line.contains(token)) { + return line.split(token)[1].trim(); + } + return null; + } + + public GlusterServer getGlusterServer(GlusterServer onlineServer, String serverName) { + List servers = getGlusterServers(onlineServer); + for (GlusterServer server : servers) { + if (server.getName().equals(serverName)) { + return server; + } + } + return null; + } + + private String getUuid(String serverName) { + ProcessResult result = getSshUtil().executeRemote(serverName, "cat " + GLUSTERD_INFO_FILE); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't read file [" + GLUSTERD_INFO_FILE + "]. Error: " + + result.toString()); + } + return result.getOutput().split("=")[1]; + } + + public List getGlusterServers(GlusterServer knownServer) { + String output = getPeerStatus(knownServer.getName()); + if (output == null) { + return null; + } + + knownServer.setUuid(getUuid(knownServer.getName())); + + List glusterServers = new ArrayList(); + glusterServers.add(knownServer); + + GlusterServer server = null; + boolean foundHost = false; + boolean foundUuid = false; + for (String line : output.split(CoreConstants.NEWLINE)) { + if (foundHost && foundUuid) { + // Host and UUID is found, we should look for state + String state = extractToken(line, STATE_PFX); + if (state != null) { + server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE + : SERVER_STATUS.OFFLINE); + // Completed populating current server. Add it to the list + // and reset all related variables. + glusterServers.add(server); + + foundHost = false; + foundUuid = false; + server = null; + } + } else if (foundHost) { + // Host is found, look for UUID + String uuid = extractToken(line, UUID_PFX); + if (uuid != null) { + server.setUuid(uuid); + foundUuid = true; + } + } else { + // Look for the next host + if (server == null) { + server = new GlusterServer(); + } + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + server.setName(hostName); + foundHost = true; + } + } + + } + return glusterServers; + } + + public List getGlusterServerNames(String knownServer) { + String output = getPeerStatus(knownServer); + if (output == null) { + return null; + } + + List glusterServerNames = new ArrayList(); + for (String line : output.split(CoreConstants.NEWLINE)) { + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + glusterServerNames.add(hostName); + } + } + return glusterServerNames; + } + + /** + * @param knownServer + * A known server on which the gluster command will be executed to fetch peer status + * @return Outout of the "gluster peer status" command + */ + private String getPeerStatus(String knownServer) { + String output; + ProcessResult result = getSshUtil().executeRemote(knownServer, "gluster peer status"); + if (!result.isSuccess()) { + output = null; + } + output = result.getOutput(); + return output; + } + + public void addServer(String existingServer, String newServer) { + ProcessResult result = sshUtil.executeRemote(existingServer, "gluster peer probe " + newServer); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't probe server [" + newServer + "] from [" + existingServer + + "]. Error: " + result); + } + + // reverse peer probe to ensure that host names appear in peer status on both sides + result = sshUtil.executeRemote(newServer, "gluster peer probe " + existingServer); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't _reverse_ probe server [" + existingServer + "] from [" + + newServer + "]. Error: " + result); + } + } + + public Status startVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster volume start " + volumeName)); + } + + public Status stopVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume stop " + volumeName)); + } + + public void resetOptions(String volumeName, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't reset options for volume [" + volumeName + "]! Error: " + + result); + } + } + + public void createVolume(String knownServer, String volumeName, String volumeTypeStr, String transportTypeStr, + Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, String options) { + + int count = 1; // replica or stripe count + + VOLUME_TYPE volType = Volume.getVolumeTypeByStr(volumeTypeStr); + String volTypeArg = null; + if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volTypeArg = "replica"; + count = replicaCount; + } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volTypeArg = "stripe"; + count = stripeCount; + } + + String transportTypeArg = null; + TRANSPORT_TYPE transportType = Volume.getTransportTypeByStr(transportTypeStr); + transportTypeArg = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + + String command = prepareVolumeCreateCommand(volumeName, StringUtil.extractList(bricks, ","), count, + volTypeArg, transportTypeArg); + ProcessResult result = sshUtil.executeRemote(knownServer, command); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Error in creating volume [" + volumeName + "]: " + result); + } + + try { + createOptions(volumeName, StringUtil.extractMap(options, ",", "="), knownServer); + } catch(Exception e) { + throw new GlusterRuntimeException( + "Volume created successfully, however following errors occurred while setting options: " + + CoreConstants.NEWLINE + e.getMessage()); + } + } + + private String prepareVolumeCreateCommand(String volumeName, List brickDirectories, int count, + String volumeType, String transportTypeStr) { + StringBuilder command = new StringBuilder("gluster volume create " + volumeName + " "); + if (volumeType != null) { + command.append(volumeType + " " + count + " "); + } + command.append("transport " + transportTypeStr); + for (String brickDir : brickDirectories) { + command.append(" " + brickDir); + } + return command.toString(); + } + + public void createOptions(String volumeName, Map options, String knownServer) { + String errors = ""; + if (options != null) { + for (Entry option : options.entrySet()) { + String key = option.getKey(); + String value = option.getValue(); + + try { + setOption(volumeName, key, value, knownServer); + } catch(Exception e) { + // append error + errors += e.getMessage() + CoreConstants.NEWLINE; + } + } + } + if (!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Errors while setting option(s) on volume [" + volumeName + "] : " + + errors.trim()); + } + } + + public void setOption(String volumeName, String key, String value, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " + + "\"" + value + "\""); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Volume [" + volumeName + "] set [" + key + "=" + value + "] => " + + result); + } + } + + public Status deleteVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume delete " + volumeName)); + } + + private String getVolumeInfo(String volumeName, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info " + volumeName); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [gluster volume info " + volumeName + "] failed on [" + + knownServer + "] with error: " + result); + } + return result.getOutput(); + } + + private String getVolumeInfo(String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info "); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [gluster volume info] failed on [" + knownServer + + "] with error: " + result); + } + return result.getOutput(); + } + + private boolean readVolumeType(Volume volume, String line) { + String volumeType = extractToken(line, VOLUME_TYPE_PFX); + if (volumeType != null) { + if (volumeType.equals(VOLUME_TYPE_DISTRIBUTE)) { + volume.setVolumeType(VOLUME_TYPE.PLAIN_DISTRIBUTE); + } else if (volumeType.equals(VOLUME_TYPE_REPLICATE)) { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_MIRROR); + volume.setReplicaCount(Volume.DEFAULT_REPLICA_COUNT); + } else { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_STRIPE); + volume.setStripeCount(Volume.DEFAULT_STRIPE_COUNT); + } + return true; + } + return false; + } + + private void readReplicaOrStripeCount(Volume volume, String line) { + if (extractToken(line, "x") != null) { + // expected formated of line is "Number of Bricks: 3 x 2 = 6" + int count = Integer.parseInt(line.split("x")[1].split("=")[0].trim()); + if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volume.setStripeCount(count); + } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volume.setReplicaCount(count); + volume.setStripeCount(0); + } + + } + return; + } + + private boolean readVolumeStatus(Volume volume, String line) { + String volumeStatus = extractToken(line, VOLUME_STATUS_PFX); + if (volumeStatus != null) { + volume.setStatus(volumeStatus.equals("Started") ? VOLUME_STATUS.ONLINE : VOLUME_STATUS.OFFLINE); + return true; + } + return false; + } + + private boolean readTransportType(Volume volume, String line) { + String transportType = extractToken(line, VOLUME_TRANSPORT_TYPE_PFX); + if (transportType != null) { + volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET : TRANSPORT_TYPE.INFINIBAND); + return true; + } + return false; + } + + private boolean readBrick(Volume volume, String brickLine) { + BRICK_STATUS brickStatus; + if (brickLine.matches("Brick[0-9]+:.*")) { + // line: "Brick1: server1:/export/md0/volume-name" + String brickName = brickLine.split(": ")[1]; + String[] brickParts = brickLine.split(":"); + String serverName = brickParts[1].trim(); + String brickDir = brickParts[2].trim(); + //To get the brick status + brickStatus = getBrickStatus(serverName, volume.getName(), brickName); + + addBrickToVolume(volume, serverName, brickDir, brickStatus); + return true; + } + return false; + } + + private void addBrickToVolume(Volume volume, String serverName, String brickDir, BRICK_STATUS status) { + //If brick directory has standard path, find and assign device name otherwise null + String stdBrickDirPattern = "^/export/.*/.*"; // e.g: /export/sdb/test + String deviceName = null; + if (Pattern.matches(stdBrickDirPattern, brickDir) ) { + deviceName = brickDir.split("/")[2].trim(); + } + volume.addBrick(new Brick(serverName, status, deviceName, brickDir)); + } + + // Do not throw exception, Gracefully handle as Offline brick. + private BRICK_STATUS getBrickStatus(String serverName, String volumeName, String brick){ + try { + ProcessResult output = getSshUtil().executeRemote(serverName, "get_brick_status.py" + " " + volumeName + " " + brick); + + if (output.isSuccess() && output.getOutput().equals(CoreConstants.ONLINE)) { + return BRICK_STATUS.ONLINE; + } else { + return BRICK_STATUS.OFFLINE; + } + } catch(Exception e) { // Particularly interested on ConnectionExecption, if the server is offline + return BRICK_STATUS.OFFLINE; + } + } + + private boolean readBrickGroup(String line) { + return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; + } + + private boolean readOptionReconfigGroup(String line) { + return extractToken(line, VOLUME_OPTIONS_RECONFIG_PFX) != null; + } + + private boolean readOption(Volume volume, String line) { + if (line.matches("^[^:]*:.*$")) { + int index = line.indexOf(':'); + volume.setOption(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim()); + + if (line.substring(0, index).trim().equals(Volume.OPTION_NFS_DISABLE)) { + if (line.substring(index + 1, line.length()).trim().equals(GlusterConstants.ON)) { + volume.disableNFS(); + } else { + volume.enableNFS(); + } + } + + return true; + } + return false; + } + + public Volume getVolume(String volumeName, String knownServer) { + return parseVolumeInfo(getVolumeInfo(volumeName, knownServer)).get(0); + } + + public List getAllVolumes(String knownServer) { + return parseVolumeInfo(getVolumeInfo(knownServer)); + } + + private List parseVolumeInfo(String volumeInfoText) { + List volumes = new ArrayList(); + boolean isBricksGroupFound = false; + boolean isOptionReconfigFound = false; + Volume volume = null; + + for (String line : volumeInfoText.split(CoreConstants.NEWLINE)) { + String volumeName = extractToken(line, VOLUME_NAME_PFX); + if (volumeName != null) { + if (volume != null) { + volumes.add(volume); + } + + // prepare next volume to be read + volume = new Volume(); + volume.setName(volumeName); + isBricksGroupFound = isOptionReconfigFound = false; + continue; + } + + if (readVolumeType(volume, line)) + continue; + if (extractToken(line, VOLUME_NUMBER_OF_BRICKS) != null) { + readReplicaOrStripeCount(volume, line); + } + if (readVolumeStatus(volume, line)) + continue; + if (readTransportType(volume, line)) + continue; + if (readBrickGroup(line)) { + isBricksGroupFound = true; + continue; + } + + if (isBricksGroupFound) { + if (readBrick(volume, line)) { + continue; + } else { + isBricksGroupFound = false; + } + } + + if (readOptionReconfigGroup(line)) { + isOptionReconfigFound = true; + continue; + } + + if (isOptionReconfigFound) { + if (readOption(volume, line)) { + continue; + } else { + isOptionReconfigFound = false; + } + } + } + + if (volume != null) {// Adding the last volume parsed + volumes.add(volume); + } + + return volumes; + } + + public void addBricks(String volumeName, List bricks, String knownServer) { + StringBuilder command = new StringBuilder("gluster volume add-brick " + volumeName); + for (String brickDir : bricks) { + command.append(" " + brickDir); + } + + ProcessResult result = sshUtil.executeRemote(knownServer, command.toString()); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Error in volume [" + volumeName + "] add-brick [" + bricks + "]: " + + result); + } + } + + public String getLogLocation(String volumeName, String brickName, String knownServer) { + String command = "gluster volume log locate " + volumeName + " " + brickName; + ProcessResult result = sshUtil.executeRemote(knownServer, command); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [" + command + "] failed with error: [" + result.getExitValue() + + "][" + result.getOutput() + "]"); + } + String output = result.getOutput(); + if (output.startsWith(VOLUME_LOG_LOCATION_PFX)) { + return output.substring(VOLUME_LOG_LOCATION_PFX.length()).trim(); + } + + throw new GlusterRuntimeException("Couldn't parse output of command [" + command + "]. Output [" + output + + "] doesn't start with prefix [" + VOLUME_LOG_LOCATION_PFX + "]"); + } + + public String getLogFileNameForBrickDir(String brickDir) { + String logFileName = brickDir; + if (logFileName.startsWith(File.separator)) { + logFileName = logFileName.replaceFirst(File.separator, ""); + } + logFileName = logFileName.replaceAll(File.separator, "-") + ".log"; + return logFileName; + } + + public Status removeBricks(String volumeName, List bricks, String knownServer) { + StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName); + for (String brickDir : bricks) { + command.append(" " + brickDir); + } + return new Status(sshUtil.executeRemote(knownServer, command.toString())); + } + + public void removeServer(String existingServer, String serverName) { + ProcessResult result = sshUtil.executeRemote(existingServer, "gluster --mode=script peer detach " + serverName); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); + } + } + + public TaskStatus checkRebalanceStatus(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " status"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches("^rebalance completed.*")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if(processResult.getOutput().trim().matches(".*in progress.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + return taskStatus; + } + + public void stopRebalance(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " stop"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + } + } + + public TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { + Object response = serverUtil.executeOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + diskName, + InitDiskStatusResponse.class); + + TaskStatus taskStatus = new TaskStatus(); + if (response instanceof Status) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(((Status) response).getMessage()); + throw new GlusterRuntimeException(((Status) response).getMessage()); + } + + InitDiskStatusResponse initDiskStatusResponse = (InitDiskStatusResponse) response; + + if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.COMPLETED) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.IN_PROGRESS) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + taskStatus.setPercentCompleted(Math.round(initDiskStatusResponse.getCompletedBlocks() + / initDiskStatusResponse.getTotalBlocks() * 100)); + } else if(initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.NOT_RUNNING) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + + taskStatus.setMessage(initDiskStatusResponse.getMessage()); + return taskStatus; + } + + public ProcessResult executeBrickMigration(String onlineServerName, String volumeName, String fromBrick, + String toBrick, String operation) { + String command = "gluster volume replace-brick " + volumeName + " " + fromBrick + " " + toBrick + " " + operation; + ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); + if (!processResult.isSuccess()) { + throw new GlusterRuntimeException(processResult.toString()); + } + return processResult; + } + + public static void main(String args[]) { + // List names = new GlusterUtil().getGlusterServerNames(); + // System.out.println(names); + List disks = new ArrayList(); + disks.add("server1:sda"); + disks.add("server1:sdb"); + new GlusterUtil().addBricks("Volume3", disks, "localhost"); + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java new file mode 100644 index 00000000..dc88bf52 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; + +/** + * + */ +@Component +public class MemoryStatsFactory extends AbstractStatsFactory { + + private static final String MEM_STATS_SCRIPT = "get_rrd_memory_details.py"; + + @Override + public String getStatsScriptName() { + return MEM_STATS_SCRIPT; + } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // stats returned by rrd script contains five columns - user, free, cache, buffer, total + // out of this, the "user" memory includes cached and buffer. We remove them to get the + // actual memory used by "user" + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + Double user = data.get(0); + Double free = data.get(1); + Double cache = data.get(2); + Double buffer = data.get(3); + Double total = data.get(4); + + Double actualUser = user - cache - buffer; + + // convert all figures from bytes to percentages + data.set(0, (actualUser * 100) / total); + data.set(1, (free * 100) / total); + data.set(2, (cache * 100) / total); + data.set(3, (buffer * 100) / total); + data.set(4, (total * 100) / total); + } + + return stats; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java new file mode 100644 index 00000000..d3d47c58 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; + +/** + * + */ +@Component +public class NetworkStatsFactory extends AbstractStatsFactory { + private static final Logger logger = Logger.getLogger(NetworkStatsFactory.class); + private static final String NETWORK_STATS_SCRIPT = "get_rrd_net_details.py"; + private int[][] dataCount; + + @Override + public String getStatsScriptName() { + return NETWORK_STATS_SCRIPT; + } + + @Override + protected ServerStats getFirstOnlineServerStats(List serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + ServerStats firstOnlineServerStats = null; + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + try { + for(NetworkInterface networkInterface : server.getNetworkInterfaces()) { + ServerStats stats = fetchStats(serverName, period, networkInterface.getName()); + if(firstOnlineServerStats == null) { + firstOnlineServerStats = stats; + int rowCount = firstOnlineServerStats.getMetadata().getRowCount(); + int columnCount = firstOnlineServerStats.getMetadata().getLegend().size(); + dataCount = initDataCountArray(rowCount, columnCount); + } else { + addServerStats(stats, firstOnlineServerStats, dataCount); + } + } + + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return firstOnlineServerStats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + for (String serverName : serverNames) { + try { + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + + for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); + } + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s + int step = stats.getMetadata().getStep(); + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + for (int i = 0; i < data.size(); i++) { + Double val = data.get(i); + data.set(i, val / 1024 / step); + } + } + + return stats; + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java new file mode 100644 index 00000000..0fae0078 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java @@ -0,0 +1,258 @@ +/** + * ServerUtil.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.gateway.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.response.GenericResponse; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; + +@Component +public class ServerUtil { + @Autowired + ServletContext servletContext; + + @Autowired + private SshUtil sshUtil; + + private static final Logger logger = Logger.getLogger(ServerUtil.class); + + private static final String SCRIPT_DIR = "scripts"; + private static final String SCRIPT_COMMAND = "python"; + private static final String REMOTE_SCRIPT_GET_DISK_FOR_DIR = "get_disk_for_dir.py"; + private static final String REMOTE_SCRIPT_GET_SERVER_DETAILS = "get_server_details.py"; + + public void setSshUtil(SshUtil sshUtil) { + this.sshUtil = sshUtil; + } + + public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List arguments) { + List command = new ArrayList(); + + command.add(SCRIPT_COMMAND); + command.add(getScriptPath(scriptName)); + command.addAll(arguments); + return new ProcessUtil().executeCommand(runInForeground, command); + } + + private String getScriptPath(String scriptName) { + String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; + return scriptPath; + } + + /** + * Fetch details of the given server. The server name must be populated in the object before calling this method. + * + * @param server + * Server whose details are to be fetched + */ + public void fetchServerDetails(Server server) { + Object response = fetchServerDetails(server.getName()); + server.copyFrom((Server) response); // Update the details in object + server.setDisks(((Server) response).getDisks()); + } + + public String fetchHostName(String serverName) { + Object response = fetchServerDetails(serverName); + return ((Server) response).getName(); + } + + private Object fetchServerDetails(String serverName) { + // fetch standard server details like cpu, disk, memory details + Object response = executeOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); + if (response instanceof Status) { + throw new GlusterRuntimeException(((Status) response).getMessage()); + } + return response; + } + + /** + * Executes given command on given server + * + * @param runInForeground + * @param serverName + * @param commandWithArgs + * @param expectedClass + * Class of the object expected from script execution + * @return Object of the expected class from remote execution of the command. In case the remote execution fails + * ungracefully, an object of class {@link Status} will be returned. + */ + @SuppressWarnings("rawtypes") + public Object executeOnServer(boolean runInForeground, String serverName, String commandWithArgs, + Class expectedClass) { + try { + String output = executeOnServer(serverName, commandWithArgs); + + // In case the script execution exits ungracefully, the agent would return a GenericResponse. + // hence pass last argument as true to try GenericResponse unmarshalling in such cases. + Object response = unmarshal(expectedClass, output, expectedClass != GenericResponse.class); + if (expectedClass != GenericResponse.class && response instanceof GenericResponse) { + // expected class was not GenericResponse, but that's what we got. This means the + // script failed ungracefully. Extract and return the status object from the response + return ((GenericResponse) response).getStatus(); + } + return response; + } catch (RuntimeException e) { + // Except for connection exception, wrap any other exception in the a object and return it. + if (e instanceof ConnectionException) { + throw e; + } else { + // error during unmarshalling. return status with error from exception. + return new Status(e); + } + } + } + + private String executeOnServer(String serverName, String commandWithArgs) { + ProcessResult result = sshUtil.executeRemote(serverName, commandWithArgs); + + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [" + commandWithArgs + "] failed on [" + serverName + + "] with error [" + result.getExitValue() + "][" + result.getOutput() + "]"); + } + return result.getOutput(); + } + + // This is the old executeOnServer that used socket communication. + // We can keep it commented for the time being. + // private String executeOnServerUsingSocket(String serverName, String commandWithArgs) { + // try { + // InetAddress address = InetAddress.getByName(serverName); + // Socket connection = new Socket(address, 50000); + // + // PrintWriter writer = new PrintWriter(connection.getOutputStream(), true); + // writer.println(commandWithArgs); + // writer.println(); // empty line means end of request + // + // InputStream inputStream = connection.getInputStream(); + // int available = inputStream.available(); + // + // StringBuffer output = new StringBuffer(); + // if( available > 0 ) { + // // This happens when PeerAgent sends complete file + // byte[] responseData = new byte[available]; + // inputStream.read(responseData); + // output.append(new String(responseData, "UTF-8")); + // } else { + // // This happens in case of normal XML response from PeerAgent + // BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + // + // String line; + // while (!(line = reader.readLine()).trim().isEmpty()) { + // output.append(line + CoreConstants.NEWLINE); + // } + // } + // connection.close(); + // + // return output.toString(); + // } catch (Exception e) { + // throw new GlusterRuntimeException("Error during remote execution: [" + e.getMessage() + "]"); + // } + // } + + public void getFileFromServer(String serverName, String remoteFileName, String localDirName) { + sshUtil.getFile(serverName, remoteFileName, localDirName); + } + + /** + * Unmarshals given input string into object of given class + * + * @param expectedClass + * Class whose object is expected + * @param input + * Input string + * @param tryGenericResponseOnFailure + * If true, and if the unmarshalling fails for given class, another unmarshalling will be attempted with + * class {@link GenericResponse}. If this also fails, a status object with exception message is created + * and returned. + * @return Object of given expected class, or a status object in case first unmarshalling fails. + */ + @SuppressWarnings("rawtypes") + private Object unmarshal(Class expectedClass, String input, boolean tryGenericResponseOnFailure) { + try { + // create JAXB context and instantiate marshaller + JAXBContext context = JAXBContext.newInstance(expectedClass); + Unmarshaller um = context.createUnmarshaller(); + return um.unmarshal(new ByteArrayInputStream(input.getBytes())); + } catch (JAXBException e) { + if (tryGenericResponseOnFailure) { + // unmarshalling failed. try to unmarshal a GenericResponse object + return unmarshal(GenericResponse.class, input, false); + + } + return new Status(Status.STATUS_CODE_FAILURE, "Error during unmarshalling string [" + input + + "] for class [" + expectedClass.getName() + ": [" + e.getMessage() + "]"); + } + } + + /** + * @param serverName + * Server on which the directory is present + * @param brickDir + * Directory whose disk is to be fetched + * @return Status object containing the disk name, or error message in case the remote script fails. + */ + public Status getDiskForDir(String serverName, String brickDir) { + return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); + } + + public static void main(String[] args) { +// ServerStats stats = new ServerUtil().fetchCPUUsageData("s1", "1d"); +// for(ServerStatsRow row : stats.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// JAXBContext context; +// try { +// context = JAXBContext.newInstance(ServerStats.class); +// Marshaller m = context.createMarshaller(); +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// m.marshal(stats, out); +// ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); +// for(ServerStatsRow row : stats1.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// } catch (JAXBException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java new file mode 100644 index 00000000..39dd42f9 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java @@ -0,0 +1,388 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import ch.ethz.ssh2.ChannelCondition; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.SCPClient; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.utils.FileUtil; +import com.gluster.storage.management.core.utils.LRUCache; +import com.gluster.storage.management.core.utils.ProcessResult; + +/** + * + */ +@Component +public class SshUtil { + private static final String TEMP_DIR = "/tmp/"; + public static final String SSH_AUTHORIZED_KEYS_DIR_LOCAL = "/opt/glustermg/keys/"; + public static final String SSH_AUTHORIZED_KEYS_DIR_REMOTE = "/root/.ssh/"; + private static final String SSH_AUTHORIZED_KEYS_FILE = "authorized_keys"; + private static final String SSH_AUTHORIZED_KEYS_PATH_REMOTE = SSH_AUTHORIZED_KEYS_DIR_REMOTE + SSH_AUTHORIZED_KEYS_FILE; + public static final File PRIVATE_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa"); + public static final File PUBLIC_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa.pub"); +// private static final String SCRIPT_DISABLE_SSH_PASSWORD_AUTH = "disable-ssh-password-auth.sh"; + private static final String PRIVATE_KEY_PASSPHRASE = "gluster"; + private LRUCache sshConnCache = new LRUCache(10); + + // TODO: Make user name configurable + private static final String USER_NAME = "root"; + // TODO: Make default password configurable + private static final String DEFAULT_PASSWORD = "syst3m"; + + private static final Logger logger = Logger.getLogger(SshUtil.class); + + @Autowired + private Integer sshConnectTimeout; + @Autowired + private Integer sshKexTimeout; + @Autowired + private Integer sshExecTimeout; + + public boolean hasDefaultPassword(String serverName) { + try { + getConnectionWithPassword(serverName); + return true; + } catch(ConnectionException e) { + return false; + } + } + + public boolean isPublicKeyInstalled(String serverName) { + try { + getConnection(serverName); + return true; + } catch(ConnectionException e) { + return false; + } + } + + public void getFile(String serverName, String remoteFile, String localDir) { + try { + Connection conn = getConnection(serverName); + SCPClient scpClient = new SCPClient(conn); + scpClient.get(remoteFile, localDir); + } catch (IOException e) { + throw new GlusterRuntimeException("Error while fetching file [" + remoteFile + "] from server [" + + serverName + "]", e); + } + } + + public synchronized void installPublicKey(String serverName) { + Connection conn = getConnectionWithPassword(serverName); + SCPClient scpClient = new SCPClient(conn); + + // delete file if it exists + File localTempFile = new File(TEMP_DIR + SSH_AUTHORIZED_KEYS_FILE); + if(localTempFile.exists()) { + localTempFile.delete(); + } + try { + // get authorized_keys from server + scpClient.get(SSH_AUTHORIZED_KEYS_PATH_REMOTE, TEMP_DIR); + } catch (IOException e) { + // file doesn't exist. it will get created. + } + + byte[] publicKeyData; + try { + publicKeyData = FileUtil.readFileAsByteArray(PUBLIC_KEY_FILE); + } catch (Exception e) { + throw new GlusterRuntimeException("Couldn't load public key file [" + PUBLIC_KEY_FILE + "]", e); + } + + try { + // append it + FileOutputStream outputStream = new FileOutputStream(localTempFile, true); + outputStream.write(CoreConstants.NEWLINE.getBytes()); + outputStream.write(publicKeyData); + outputStream.close(); + } catch (Exception e) { + throw new GlusterRuntimeException("Couldnt append file [" + localTempFile + "] with public key!", e); + } + + try { + scpClient.put(localTempFile.getAbsolutePath(), SSH_AUTHORIZED_KEYS_FILE, SSH_AUTHORIZED_KEYS_DIR_REMOTE, "0600"); + } catch (IOException e) { + throw new GlusterRuntimeException("Couldn't add public key to server [" + serverName + "]", e); + } + + // It was decided NOT to disable password login as this may not be acceptable in a bare-metal environment + // disableSshPasswordLogin(serverName, scpClient); + } + +// private void disableSshPasswordLogin(String serverName, SCPClient scpClient) { +// ProcessResult result = executeRemote(serverName, SCRIPT_DISABLE_SSH_PASSWORD_AUTH); +// if(!result.isSuccess()) { +// throw new GlusterRuntimeException("Couldn't disable SSH password authentication on [" + serverName +// + "]. Error: " + result); +// } +// } + + private Connection getConnectionWithPassword(String serverName) { + Connection conn = createConnection(serverName); + authenticateWithPassword(conn); + return conn; + } + + private synchronized Connection getConnection(String serverName) { + Connection conn = sshConnCache.get(serverName); + if (conn != null) { + return conn; + } + + conn = createConnection(serverName); + authenticateWithPublicKey(conn); + sshConnCache.put(serverName, conn); + return conn; + } + + private void authenticateWithPublicKey(Connection conn) { + try { + if (!supportsPublicKeyAuthentication(conn)) { + throw new ConnectionException("Public key authentication not supported on [" + conn.getHostname() + + "]"); + } + + if (!conn.authenticateWithPublicKey(USER_NAME, PRIVATE_KEY_FILE, PRIVATE_KEY_PASSPHRASE)) { + throw new ConnectionException("SSH Authentication (public key) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new ConnectionException("Exception during SSH authentication (public key) for server [" + + conn.getHostname() + "]", e); + } + } + + private void authenticateWithPassword(Connection conn) { + try { + if (!supportsPasswordAuthentication(conn)) { + throw new ConnectionException("Password authentication not supported on [" + conn.getHostname() + + "]"); + } + + if (!conn.authenticateWithPassword(USER_NAME, DEFAULT_PASSWORD)) { + throw new ConnectionException("SSH Authentication (password) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new ConnectionException("Exception during SSH authentication (password) for server [" + + conn.getHostname() + "]", e); + } + } + + private boolean supportsPasswordAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("password"); + } + + private boolean supportsPublicKeyAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("publickey"); + } + + private Connection createConnection(String serverName) { + Connection conn; + conn = new Connection(serverName); + try { + conn.connect(null, sshConnectTimeout, sshKexTimeout); + } catch (IOException e) { + logger.error("Couldn't establish SSH connection with server [" + serverName + "]", e); + throw new ConnectionException("Exception while creating SSH connection with server [" + serverName + "]", e); + } + return conn; + } + + private boolean wasTerminated(int condition) { + return ((condition | ChannelCondition.EXIT_SIGNAL) == condition); + } + + private boolean hasErrors(int condition, Session session) { + return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session))); + } + + private boolean timedOut(int condition) { + return (condition == ChannelCondition.TIMEOUT); + } + + private boolean exitedWithError(Session session) { + return session.getExitStatus() != ProcessResult.SUCCESS; + } + + private boolean exitedGracefully(int condition) { + return (condition | ChannelCondition.EXIT_STATUS) == condition; + } + + private boolean hasErrorStream(int condition) { + return (condition | ChannelCondition.STDERR_DATA) == condition; + } + + private ProcessResult executeCommand(Connection sshConnection, String command) { + try { + Session session = sshConnection.openSession(); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStdout()))); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStderr()))); + session.execCommand(command); + ProcessResult result = getResultOfExecution(session, stdoutReader, stderrReader); + session.close(); + return result; + } catch (IOException e) { + String errMsg = "Exception while executing command [" + command + "] on [" + sshConnection.getHostname() + + "]"; + logger.error(errMsg, e); + throw new GlusterRuntimeException(errMsg, e); + } + } + + private ProcessResult getResultOfExecution(Session session, BufferedReader stdoutReader, BufferedReader stderrReader) { + // Wait for program to come out either + // a) gracefully with an exit status, OR + // b) because of a termination signal + // c) command takes to long to exit (timeout) + int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, + sshExecTimeout); + StringBuilder output = new StringBuilder(); + + try { + if(!timedOut(condition)) { + readFromStream(stdoutReader, output); + if (hasErrors(condition, session)) { + readFromStream(stderrReader, output); + } + } + + return prepareProcessResult(session, condition, output.toString().trim()); + } catch (IOException e) { + String errMsg = "Error while reading output stream from SSH connection!"; + logger.error(errMsg, e); + return new ProcessResult(ProcessResult.FAILURE, errMsg); + } + } + + private ProcessResult prepareProcessResult(Session session, int condition, String output) { + ProcessResult result = null; + + if (wasTerminated(condition)) { + result = new ProcessResult(ProcessResult.FAILURE, output); + } else if (timedOut(condition)) { + result = new ProcessResult(ProcessResult.FAILURE, "Command timed out!"); + } else if (hasErrors(condition, session)) { + Integer exitStatus = session.getExitStatus(); + int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus); + result = new ProcessResult(statusCode, output); + } else { + result = new ProcessResult(ProcessResult.SUCCESS, output); + } + + return result; + } + + private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException { + while (true) { + String line = streamReader.readLine(); + if (line == null) { + break; + } + output.append(line + CoreConstants.NEWLINE); + } + } + + /** + * Executes given command on remote machine using password authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemoteWithPassword(String serverName, String command) { + return executeCommand(getConnectionWithPassword(serverName), command); + } + + private ProcessResult executeRemoteWithPubKey(String serverName, String command) { + try { + return executeCommand(getConnection(serverName), command); + } catch(GlusterRuntimeException e) { + Throwable cause = e.getCause(); + if(cause != null && cause instanceof IOException) { + // cached ssh connection might have gone bad. + // remove it and try with a new one + sshConnCache.remove(serverName); + return executeCommand(getConnection(serverName), command); + } else { + throw e; + } + } + } + + /** + * Executes given command on remote machine using public key authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemote(String serverName, String command) { + try { + return executeRemoteWithPubKey(serverName, command); + } catch(ConnectionException e) { + // Couldn't connect with public key. Try with default password. + return executeRemoteWithPassword(serverName, command); + } + } + + /** + * Checks if public key of management gateway is configured on given server + * + * @param serverName + * @return true if public key is configured, else false + */ + public boolean isPublicKeySetup(String serverName) { + try { + getConnection(serverName); + return true; + } catch (Exception e) { + return false; + } + } + + public void cleanup() { + for (Connection conn : sshConnCache.values()) { + conn.close(); + } + } +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java new file mode 100644 index 00000000..09851367 --- /dev/null +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import com.gluster.storage.management.core.model.ServerStats; + +/** + * + */ +public interface StatsFactory { + public ServerStats fetchStats(String serverName, String period, String...args); + public ServerStats fetchAggregatedStats(List serverName, String period); +} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java deleted file mode 100644 index 5c9a6505..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/constants/VolumeOptionsDefaults.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * DefaultVolumeOptions.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.constants; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.model.VolumeOptionInfo; - -@Component -public class VolumeOptionsDefaults { - public List options; - - public VolumeOptionsDefaults() { - } - - /** - * @return list of volume option information objects - */ - public List getDefaults() { - return getVolumeOptionsInfo(); - } - - /** - * Fetches the list of all volume options with their information from GlusterFS and returns the same - * - * @return List of volume option information objects - */ - private List getVolumeOptionsInfo() { - List volumeOptionsInfo = new ArrayList(); - - volumeOptionsInfo - .add(new VolumeOptionInfo( - "cluster.stripe-block-size", - "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " - + CoreConstants.NEWLINE - + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern . ", - "*:128KB")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "cluster.self-heal-window-size", - "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", - "16")); - volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", - "cluster.data-self-heal-algorithm", "auto")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "network.frame-timeout", - "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", - "1800")); - volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", - "The time duration for which the client waits to check if the server is responsive.", "42")); - volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", - "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); - volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", - "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "performance.cache-refresh-timeout", - "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", - "1")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", - "Size of the per-file write-behind buffer.", "1MB")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", - "performance.cache-max-file-size", "-1")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", - "performance.cache-min-file-size", "0")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "performance.io-thread-count", - " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", - "16")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "diagnostics.latency-measurement", - "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", - "off")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", - "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", - "Changes the log-level of the bricks (servers).", "INFO")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", - "Changes the log-level of the clients.", "INFO")); - volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", - "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", - "off")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "nfs.mem-factor", - "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", - "15")); - volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); - - return volumeOptionsInfo; - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ClusterInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ClusterInfo.java deleted file mode 100644 index 1c3cd347..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ClusterInfo.java +++ /dev/null @@ -1,79 +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.data; - -import java.util.ArrayList; -import java.util.List; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; - -import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.tool.hbm2ddl.SchemaExport; - -@Entity(name="cluster_info") -public class ClusterInfo { - @Id - @GeneratedValue - private Integer id; - - private String name; - - @OneToMany(mappedBy="cluster") - private List servers = new ArrayList(); - - public void setId(Integer id) { - this.id = id; - } - - public Integer getId() { - return id; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setServers(List servers) { - this.servers = servers; - } - - public List getServers() { - return servers; - } - - public void addServer(ServerInfo server) { - servers.add(server); - } - - public static void main(String args[]) { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.addAnnotatedClass(ClusterInfo.class); - config.addAnnotatedClass(ServerInfo.class); - config.configure(); - new SchemaExport(config).create(true, true); - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java deleted file mode 100644 index e669a130..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/GlusterDataSource.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * GlusterDataSource.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.data; - -import javax.servlet.ServletContext; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.stereotype.Component; - -@Component -public class GlusterDataSource extends DriverManagerDataSource { - @Autowired - ServletContext servletContext; - - public GlusterDataSource() { - setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); - - setUsername("gluster"); - // TODO: change to a stronger (encrypted) password - setPassword("gluster"); - } - - public DriverManagerDataSource getDataSource() { - // Database directory = work/data relative to context root - setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); - - return this; - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/PersistenceDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/PersistenceDao.java deleted file mode 100644 index 85fefcdf..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/PersistenceDao.java +++ /dev/null @@ -1,113 +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.data; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityTransaction; -import javax.persistence.PersistenceUnit; -import javax.persistence.Query; - -/** - * - */ -public class PersistenceDao { - private Class type; - - private EntityManager entityManager; - - @PersistenceUnit - private EntityManagerFactory entityManagerFactory; - - public PersistenceDao(Class type) { - this.type = type; - } - - public EntityTransaction startTransaction() { - EntityTransaction txn = getEntityManager().getTransaction(); - txn.begin(); - return txn; - } - - private synchronized EntityManager getEntityManager() { - if (entityManager == null) { - entityManager = entityManagerFactory.createEntityManager(); - } - return entityManager; - } - - public Object getSingleResult(String query) { - return getEntityManager().createQuery(query).getSingleResult(); - } - - public Object getSingleResult(String queryString, String... params) { - return createQuery(queryString, params).getSingleResult(); - } - - private Query createQuery(String queryString, String... params) { - Query query = getEntityManager().createQuery(queryString); - for (int i = 0; i < params.length; i++) { - query.setParameter(i + 1, params[i]); - } - return query; - } - - public Object getSingleResultFromSQL(String sqlQuery) { - return getEntityManager().createNativeQuery(sqlQuery).getSingleResult(); - } - - @SuppressWarnings("rawtypes") - public List findBySQL(String sqlQuery) { - return getEntityManager().createNativeQuery(sqlQuery).getResultList(); - } - - public T findById(int id) { - return getEntityManager().find(type, id); - } - - @SuppressWarnings("unchecked") - public List findAll() { - return getEntityManager().createQuery("select t from " + type.getName() + " t").getResultList(); - } - - @SuppressWarnings("unchecked") - public List findBy(String whereClause) { - return getEntityManager().createQuery("select t from " + type.getName() + " t where " + whereClause) - .getResultList(); - } - - @SuppressWarnings("unchecked") - public List findBy(String whereClause, String... params) { - return createQuery("select t from " + type.getName() + " t where " + whereClause, params).getResultList(); - } - - public void save(Object obj) { - getEntityManager().persist(obj); - } - - public T update(T obj) { - return getEntityManager().merge(obj); - } - - public void delete(Object obj) { - getEntityManager().remove(obj); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ServerInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ServerInfo.java deleted file mode 100644 index 72818200..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/data/ServerInfo.java +++ /dev/null @@ -1,72 +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.data; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; - -/** - * - */ -@Entity(name="server_info") -public class ServerInfo { - @Id - @GeneratedValue - private Integer id; - - private String name; - - @ManyToOne - @JoinColumn(name="cluster_id") - private ClusterInfo cluster; - - public ServerInfo() { - } - - public ServerInfo(String name) { - setName(name); - } - - public void setId(Integer id) { - this.id = id; - } - - public Integer getId() { - return id; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setCluster(ClusterInfo cluster) { - this.cluster = cluster; - } - - public ClusterInfo getCluster() { - return cluster; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuditFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuditFilter.java deleted file mode 100644 index daaf8f33..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuditFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * - */ -package com.gluster.storage.management.server.filters; - -import com.sun.jersey.spi.container.ContainerRequest; -import com.sun.jersey.spi.container.ContainerRequestFilter; -import com.sun.jersey.spi.container.ContainerResponse; -import com.sun.jersey.spi.container.ContainerResponseFilter; -import com.sun.jersey.spi.container.ResourceFilter; - -/** - * Resource filter for maintaining audit trail of resource access - */ -public class AuditFilter implements ResourceFilter, ContainerRequestFilter, ContainerResponseFilter { - - @Override - public ContainerRequestFilter getRequestFilter() { - return this; - } - - @Override - public ContainerResponseFilter getResponseFilter() { - return this; - } - - @Override - public ContainerRequest filter(ContainerRequest req) { - System.out.println("REQUEST: [" + req.getMethod() + "][" + req.getPath() + "]"); - return req; - } - - @Override - public ContainerResponse filter(ContainerRequest req, ContainerResponse response) { - System.out.println("RESPONSE: [" + req.getMethod() + "][" + req.getPath() + "]"); - return response; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java deleted file mode 100644 index 5f828f65..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/AuthenticationFailureFilter.java +++ /dev/null @@ -1,105 +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.filters; - -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import javax.ws.rs.core.Response; - -/** - * @author root - * - */ -public class AuthenticationFailureFilter implements Filter { - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#destroy() - */ - @Override - public void destroy() { - // TODO Auto-generated method stub - - } - - public class CharResponseWrapper extends HttpServletResponseWrapper { - private CharArrayWriter output; - - public String toString() { - return output.toString(); - } - - public CharResponseWrapper(HttpServletResponse response) { - super(response); - output = new CharArrayWriter(); - } - - public PrintWriter getWriter() { - return new PrintWriter(output); - } - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, - * javax.servlet.FilterChain) - */ - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, - ServletException { - HttpServletRequest request = (HttpServletRequest) req; - if (request.getRequestURI().contains("download")) { - chain.doFilter(req, res); - return; - } - - CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) res); - chain.doFilter(req, wrapper); - - if(wrapper.getStatus() == Response.Status.UNAUTHORIZED.ordinal()) { - PrintWriter out = res.getWriter(); - out.println("1Authentication Failed!"); - } - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) - */ - @Override - public void init(FilterConfig arg0) throws ServletException { - // TODO Auto-generated method stub - - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/GlusterResourceFilterFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/GlusterResourceFilterFactory.java deleted file mode 100644 index 899ba16e..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/filters/GlusterResourceFilterFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - */ -package com.gluster.storage.management.server.filters; - -import java.util.ArrayList; -import java.util.List; - -import com.sun.jersey.api.model.AbstractMethod; -import com.sun.jersey.spi.container.ResourceFilter; -import com.sun.jersey.spi.container.ResourceFilterFactory; - -/** - * Gluster resource filter factory. As of now, this creates only one filter - the audit filter {@code AuditFilter} - */ -public class GlusterResourceFilterFactory implements ResourceFilterFactory { - - public GlusterResourceFilterFactory() { - } - - /* (non-Javadoc) - * @see com.sun.jersey.spi.container.ResourceFilterFactory#create(com.sun.jersey.api.model.AbstractMethod) - */ - @Override - public List create(AbstractMethod arg0) { - List filters = new ArrayList(); - filters.add(new AuditFilter()); - - return filters; - } -} 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 deleted file mode 100644 index 21b95877..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/AbstractResource.java +++ /dev/null @@ -1,177 +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.v1_0; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; - -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.StreamingOutput; -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 - * 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(); - } - - protected StreamingOutput createStreamingOutput(final byte[] data) { - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException { - output.write(data); - } - }; - } -} 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 deleted file mode 100644 index 45125513..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/ClustersResource.java +++ /dev/null @@ -1,126 +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.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.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -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; - private static final Logger logger = Logger.getLogger(ClustersResource.class); - - @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()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); - } - - clusterService.createCluster(clusterName); - return createdResponse(clusterName); - } - - @PUT - public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, - @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { - if(clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(knownServer == null || knownServer.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); - } - - ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); - if(mappedCluster != null) { - throw new GlusterValidationException("Server [" + knownServer + "] is already present in cluster [" - + mappedCluster.getName() + "]!"); - } - - clusterService.registerCluster(clusterName, knownServer); - return noContentResponse(clusterName); - } - - @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") - @DELETE - public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - if(clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if(cluster == null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] does not exist!"); - } - - clusterService.unregisterCluster(cluster); - return noContentResponse(); - } -} 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 deleted file mode 100644 index f6038b71..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/DiscoveredServersResource.java +++ /dev/null @@ -1,150 +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.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.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; - -@Component -@Singleton -@Path(RESOURCE_PATH_DISCOVERED_SERVERS) -public class DiscoveredServersResource extends AbstractResource { - @InjectParam - protected ServerUtil serverUtil; - - @InjectParam - protected GlusterUtil glusterUtil; - - 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/GenericExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java deleted file mode 100644 index f9650902..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GenericExceptionMapper.java +++ /dev/null @@ -1,54 +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.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; - -@Provider -public class GenericExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(Exception exception) { - ResponseBuilder builder; - if (exception instanceof GlusterValidationException) { - builder = Response.status(Response.Status.BAD_REQUEST); - } else { - builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); - } - - String errMsg = exception.getMessage(); - if(errMsg == null) { - errMsg = "Following exception occurred : " + exception.getClass().getName(); - StackTraceElement[] stackTrace = exception.getStackTrace(); - if(stackTrace.length > 0) { - errMsg += " at [" + stackTrace[0].getClassName() + "][" + stackTrace[0].getLineNumber() + "]"; - } - } - return builder.entity(errMsg).type(MediaType.TEXT_PLAIN).build(); - } -} 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 deleted file mode 100644 index fa96c884..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/GlusterServersResource.java +++ /dev/null @@ -1,487 +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.v1_0; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE; -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.QUERY_PARAM_DETAILS; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_INTERFACE; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_PERIOD; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; -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_STATISTICS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK; - -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.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.response.GlusterServerListResponse; -import com.gluster.storage.management.core.response.ServerNameListResponse; -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.services.GlusterServerService; -import com.gluster.storage.management.server.tasks.InitializeDiskTask; -import com.gluster.storage.management.server.utils.CpuStatsFactory; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.MemoryStatsFactory; -import com.gluster.storage.management.server.utils.NetworkStatsFactory; -import com.gluster.storage.management.server.utils.ServerUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.gluster.storage.management.server.utils.StatsFactory; -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 AbstractResource { - - public static final String HOSTNAMETAG = "hostname:"; - - @InjectParam - private DiscoveredServersResource discoveredServersResource; - - @InjectParam - private TasksResource taskResource; - - @InjectParam - private ClusterService clusterService; - - @InjectParam - private SshUtil sshUtil; - - @InjectParam - private CpuStatsFactory cpuStatsFactory; - - @InjectParam - private MemoryStatsFactory memoryStatsFactory; - - @InjectParam - private NetworkStatsFactory networkStatsFactory; - - @InjectParam - private ServerUtil serverUtil; - - @InjectParam - private GlusterUtil glusterUtil; - - @InjectParam - private GlusterServerService glusterServerService; - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); - } - - private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { - if(fetchDetails == null) { - // by default, fetch the server details - fetchDetails = true; - } - - 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); - } - - try { - glusterServers = glusterServerService.getGlusterServers(clusterName, fetchDetails); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - - if(fetchDetails) { - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } else { - // no details to be fetched. Return list of server names. - return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType); - } - } - - private List getServerNames(List glusterServers) { - List serverNames = new ArrayList(); - for(GlusterServer server : glusterServers) { - serverNames.add(server.getName()); - } - return serverNames; - } - - @GET - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - @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("{" + PATH_PARAM_SERVER_NAME + "}") - @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(glusterServerService.getGlusterServer(clusterName, serverName, true), mediaType); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - 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."); - } - - String hostName = serverUtil.fetchHostName(serverName); - 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, hostName); - } 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()); - } - } - clusterService.unmapServerFromCluster(clusterName, serverName); - - 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); - } - - // 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, - @FormParam(FORM_PARAM_FSTYPE) String fsType) { - - 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!"); - } - - if (fsType == null || fsType.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_FSTYPE + "] is missing in request!"); - } - - InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName, fsType); - try { - initializeTask.start(); - // Check the initialize disk status - TaskStatus taskStatus = initializeTask.checkStatus(); - initializeTask.getTaskInfo().setStatus(taskStatus); - taskResource.addTask(initializeTask); - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + initializeTask.getId()); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - @GET - @Produces(MediaType.APPLICATION_XML) - @Path(RESOURCE_STATISTICS) - public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { - return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_XML); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path(RESOURCE_STATISTICS) - public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { - return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_JSON); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, - @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { - return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_XML); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, - @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { - return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_JSON); - } - - private Response getAggregaredPerformanceData(String clusterName, String type, String period, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (type == null || type.isEmpty()) { - throw new GlusterValidationException("Statistics type name must not be empty!"); - } - - if (period == null || period.isEmpty()) { - throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (cluster.getServers().isEmpty()) { - // cluster is empty. return empty stats. - return okResponse(new ServerStats(), mediaType); - } - - List serverNames = getServerNames(glusterServerService.getGlusterServers(clusterName, false)); - return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); - } - - private Response getPerformanceData(String clusterName, String serverName, String type, String period, String networkInterface, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterValidationException("Server name must not be empty!"); - } - - if (type == null || type.isEmpty()) { - throw new GlusterValidationException("Statistics type name must not be empty!"); - } - - if (period == null || period.isEmpty()) { - throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); - } - - return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); - } - - private StatsFactory getStatsFactory(String type) { - if(type.equals(STATISTICS_TYPE_CPU)) { - return cpuStatsFactory; - } else if(type.equals(STATISTICS_TYPE_MEMORY)) { - return memoryStatsFactory; - } else if(type.equals(STATISTICS_TYPE_NETWORK)) { - return networkStatsFactory; - } else { - throw new GlusterValidationException("Invalid server statistics type [" + type + "]. Valid values are [" - + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java deleted file mode 100644 index 807291be..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/KeysResource.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * KeysResource.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.RESOURCE_PATH_KEYS; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -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.utils.FileUtil; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.core.utils.ProcessUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.multipart.FormDataParam; - -@Path(RESOURCE_PATH_KEYS) -public class KeysResource extends AbstractResource { - private static final Logger logger = Logger.getLogger(KeysResource.class); - private ProcessUtil processUtil = new ProcessUtil(); - - @GET - @Produces(MediaType.APPLICATION_OCTET_STREAM) - public Response exportSshkeys() { - File archiveFile = new File(createSskKeyZipFile()); - byte[] data = FileUtil.readFileAsByteArray(archiveFile); - archiveFile.delete(); - return streamingOutputResponse(createStreamingOutput(data)); - } - - private String createSskKeyZipFile() { - String targetDir = System.getProperty("java.io.tmpdir"); - String zipFile = targetDir + "ssh-keys.tar"; - String sourcePemFile = SshUtil.PRIVATE_KEY_FILE.getAbsolutePath(); - String sourcePubKeyFile = SshUtil.PUBLIC_KEY_FILE.getAbsolutePath(); - String targetPemFile = targetDir + File.separator + SshUtil.PRIVATE_KEY_FILE.getName(); - String targetPubKeyFile = targetDir + File.separator + SshUtil.PUBLIC_KEY_FILE.getName(); - - if (!SshUtil.PRIVATE_KEY_FILE.isFile()) { - throw new GlusterRuntimeException("No private key file [" + SshUtil.PRIVATE_KEY_FILE.getName() + "] found!" ); - } - - if (!SshUtil.PUBLIC_KEY_FILE.isFile()) { - throw new GlusterRuntimeException("No public key file [" + SshUtil.PUBLIC_KEY_FILE.getName() + "] found!" ); - } - - // Copy keys to temp folder - ProcessResult result = processUtil.executeCommand("cp", sourcePemFile, targetPemFile); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); - } - result = processUtil.executeCommand("cp", sourcePubKeyFile, targetPubKeyFile); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); - } - - // To compress the key files - result = processUtil.executeCommand("tar", "cvf", zipFile, "-C", "/tmp", SshUtil.PRIVATE_KEY_FILE.getName(), - SshUtil.PUBLIC_KEY_FILE.getName()); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to compress key files! [" + result.getOutput() + "]"); - } - - // To remove the copied key files - try { - processUtil.executeCommand("rm", "-f", targetPemFile, targetPubKeyFile); // Ignore the errors if any - } catch (Exception e) { - logger.warn(e.toString()); - } - return zipFile; - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response importSshKeys(@FormDataParam("file") InputStream uploadedInputStream) { - File uploadedFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "keys.tar"); - String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); - - writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); - - // To backup existing SSH pem and public keys, if exist. - if (SshUtil.PRIVATE_KEY_FILE.isFile()) { - if (!SshUtil.PRIVATE_KEY_FILE.renameTo(new File(SshUtil.PRIVATE_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { - throw new GlusterRuntimeException("Unable to backup pem key!"); - } - } - - if (SshUtil.PUBLIC_KEY_FILE.isFile()) { - if (!SshUtil.PUBLIC_KEY_FILE - .renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { - throw new GlusterRuntimeException("Unable to backup public key!"); - } - } - // Extract SSH pem and public key files. - ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", - SshUtil.SSH_AUTHORIZED_KEYS_DIR_LOCAL); - uploadedFile.delete(); - if (!output.isSuccess()) { - throw new GlusterRuntimeException(output.getOutput()); - } - return createdResponse("SSH Key imported successfully"); - } - - // save uploaded file to the file (with path) - private void writeToFile(InputStream inputStream, String toFile) { - try { - int read = 0; - byte[] bytes = new byte[1024]; - - OutputStream out = new FileOutputStream(new File(toFile)); - while ((read = inputStream.read(bytes)) != -1) { - out.write(bytes, 0, read); - } - out.flush(); - out.close(); - } catch (IOException e) { - throw new GlusterRuntimeException(e.getMessage()); - } - } -} 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 deleted file mode 100644 index 0fa49dc3..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/TasksResource.java +++ /dev/null @@ -1,194 +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.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 org.springframework.stereotype.Component; - -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.Status; -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 -@Component -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; - } - - public List getAllTasks() { - List tasks = new ArrayList(); - for (Map.Entry entry : tasksMap.entrySet()) { - checkTaskStatus(entry.getKey()); - tasks.add( (Task) entry.getValue()); - } - return tasks; - } - - @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); - // No status check required if the task already complete or failure - if (task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_FAILURE - || task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { - return task; - } - 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(); - clearTask(taskId, taskOperation); // Stop and remove from the task list - } 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 clearTask(@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 deleted file mode 100644 index 1b5e8fad..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/UsersResource.java +++ /dev/null @@ -1,91 +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.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 deleted file mode 100644 index 1d0963eb..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/resources/v1_0/VolumesResource.java +++ /dev/null @@ -1,988 +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.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.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.core.MediaType; -import javax.ws.rs.core.Response; - -import org.apache.log4j.Logger; - -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"; - private static final Logger logger = Logger.getLogger(VolumesResource.class); - - @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) { - Status status; - try { - status = 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 + "]"); - } - status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } - if (!status.isSuccess()) { - throw new GlusterRuntimeException(status.toString()); - } - } - - @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); - File archiveFile = new File(downloadLogs(volume)); - byte[] data = FileUtil.readFileAsByteArray(archiveFile); - archiveFile.delete(); - return streamingOutputResponse(createStreamingOutput(data)); - } catch (Exception e) { - logger.error("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]! [" - + e.getStackTrace() + "]"); - throw (GlusterRuntimeException) e; - } - } - - - 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 getLayout(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 layout; - } - - private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, - Boolean isForcedDataMigrate) { - RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName, getLayout( - isFixLayout, isMigrateData, isForcedDataMigrate)); - 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(); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java deleted file mode 100644 index 21c13a03..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/GlusterUserDetailsService.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * GlusterUserDetailsService.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.security; - -import org.springframework.security.core.userdetails.UserDetailsService; - -/** - * - */ -public interface GlusterUserDetailsService extends UserDetailsService { - void changePassword(String username, String password); -} - diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java deleted file mode 100644 index cfc6e572..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/security/UserAuthDao.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * UserAuthDao.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.security; - -import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; - -/** - * @author root - * - */ -public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { - - /* - * (non-Javadoc) - * - * @see com.gluster.storage.management.server.security.GlusterUserDetailsService#changePassword(java.lang.String, - * java.lang.String) - */ - @Override - public void changePassword(String username, String password) { - getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); - } - -} 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 deleted file mode 100644 index 47960827..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/ClusterService.java +++ /dev/null @@ -1,269 +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.services; - -import java.util.ArrayList; -import java.util.List; - -import javax.persistence.EntityTransaction; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.core.utils.LRUCache; -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.data.ServerInfo; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.ServerUtil; -import com.gluster.storage.management.server.utils.SshUtil; - -/** - * Service class for functionality related to clusters - */ -@Component -public class ClusterService { - @Autowired - private PersistenceDao clusterDao; - - @Autowired - private PersistenceDao serverDao; - - @Autowired - private GlusterUtil glusterUtil; - - @Autowired - private SshUtil sshUtil; - - @Autowired - private ServerUtil serverUtil; - - private LRUCache onlineServerCache = new LRUCache(3); - - private static final Logger logger = Logger.getLogger(ClusterService.class); - - public void addOnlineServer(String clusterName, GlusterServer server) { - onlineServerCache.put(clusterName, server); - } - - public void removeOnlineServer(String clusterName) { - onlineServerCache.remove(clusterName); - } - - // uses cache - public GlusterServer getOnlineServer(String clusterName, String exceptServerName) { - GlusterServer server = onlineServerCache.get(clusterName); - if (server != null && !server.getName().equals(exceptServerName)) { - return server; - } - - return getNewOnlineServer(clusterName, exceptServerName); - } - - public GlusterServer getNewOnlineServer(String clusterName) { - return getNewOnlineServer(clusterName, ""); - } - - public GlusterServer getOnlineServer(String clusterName) { - return getOnlineServer(clusterName, ""); - } - - // Doesn't use cache - public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) { - ClusterInfo cluster = getCluster(clusterName); - if (cluster == null) { - throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!"); - } - - for (ServerInfo serverInfo : cluster.getServers()) { - GlusterServer server = new GlusterServer(serverInfo.getName()); - try { - serverUtil.fetchServerDetails(server); // Online status come with server details - // server is online. add it to cache and return - if (server.isOnline() && !server.getName().equals(exceptServerName)) { - addOnlineServer(clusterName, server); - return server; - } - } catch (ConnectionException e) { - // server is offline. continue checking next one. - continue; - } - } - - // no online server found. - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - public List getAllClusters() { - return clusterDao.findAll(); - } - - public ClusterInfo getCluster(String clusterName) { - List clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase()); - if(clusters.size() == 0) { - return null; - } - - return clusters.get(0); - } - - public ClusterInfo getClusterForServer(String serverName) { - List servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase()); - if(servers.size() == 0) { - return null; - } - - return servers.get(0).getCluster(); - } - - public void createCluster(String clusterName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); - - try { - clusterDao.save(cluster); - txn.commit(); - } catch (RuntimeException e) { - txn.rollback(); - logger.error("Exception while trying to save cluster [" + clusterName + "] : [" + e.getMessage() + "]", e); - throw e; - } - } - - public void registerCluster(String clusterName, String knownServer) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); - - GlusterServer server = new GlusterServer(knownServer); - try { - List glusterServers = glusterUtil.getGlusterServers(server); - List servers = new ArrayList(); - 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) { - logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); - txn.rollback(); - logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); - 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(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 { - for(ServerInfo server : cluster.getServers()) { - clusterDao.delete(server); - } - cluster.getServers().clear(); - clusterDao.update(cluster); - clusterDao.delete(cluster); - txn.commit(); - } catch (RuntimeException e) { - logger.error("Error in unregistering cluster [" + cluster.getName() + "] : " + e.getMessage(), e); - txn.rollback(); - throw e; - } - } - - public void mapServerToCluster(String clusterName, String serverName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = getCluster(clusterName); - ServerInfo server = new ServerInfo(serverName); - server.setCluster(cluster); - try { - clusterDao.save(server); - cluster.addServer(server); - clusterDao.update(cluster); - txn.commit(); - } catch (Exception e) { - txn.rollback(); - throw new GlusterRuntimeException("Couldn't create cluster-server mapping [" + clusterName + "][" - + serverName + "]! Error: " + e.getMessage(), e); - } - } - - public void unmapServerFromCluster(String clusterName, String serverName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = getCluster(clusterName); - List servers = cluster.getServers(); - for(ServerInfo server : servers) { - if(server.getName().equals(serverName)) { - servers.remove(server); - clusterDao.delete(server); - break; - } - } - try { - clusterDao.update(cluster); - txn.commit(); - } catch(Exception e) { - txn.rollback(); - throw new GlusterRuntimeException("Couldn't unmap server [" + serverName + "] from cluster [" + clusterName - + "]! Error: " + e.getMessage(), e); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java deleted file mode 100644 index e8bea530..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/services/GlusterServerService.java +++ /dev/null @@ -1,165 +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.services; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.ServerUtil; - -/** - * - */ -@Component -public class GlusterServerService { - @Autowired - protected ServerUtil serverUtil; - - @Autowired - private ClusterService clusterService; - - @Autowired - private GlusterUtil glusterUtil; - - public void fetchServerDetails(GlusterServer server) { - try { - server.setStatus(SERVER_STATUS.ONLINE); - serverUtil.fetchServerDetails(server); - } catch (ConnectionException e) { - server.setStatus(SERVER_STATUS.OFFLINE); - } - } - - public List getGlusterServers(String clusterName, boolean fetchDetails) { - List glusterServers; - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); - } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); - } - return glusterServers; - } - - private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { - 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); - } - - if (fetchDetails) { - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); - } - } - return glusterServers; - } - - private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { - String errMsg = ""; - - for (GlusterServer server : glusterServers) { - try { - fetchServerDetails(server); - } catch (Exception e) { - errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; - } - } - return errMsg; - } - - public GlusterServer getGlusterServer(String clusterName, String serverName, Boolean fetchDetails) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterValidationException("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 + "]"); - } - - return getGlusterServer(clusterName, serverName, onlineServer, fetchDetails); - } - - private GlusterServer getGlusterServer(String clusterName, String serverName, GlusterServer onlineServer, - Boolean fetchDetails) { - 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 (fetchDetails && server.isOnline()) { - fetchServerDetails(server); - } - return server; - } - - public boolean isValidServer(String clusterName, String serverName) { - try { - GlusterServer server = getGlusterServer(clusterName, serverName, false); - return server != null; - } catch(Exception e) { - return false; - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java deleted file mode 100644 index 3fe794f5..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitServerTask.java +++ /dev/null @@ -1,162 +0,0 @@ -/** - * GlusterServerInitializer.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.tasks; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import javax.servlet.ServletContext; - -import org.apache.derby.tools.ij; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.security.authentication.encoding.PasswordEncoder; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.server.data.ClusterInfo; -import com.gluster.storage.management.server.data.PersistenceDao; - -/** - * Initializes the Gluster Management Server. - */ -public class InitServerTask extends JdbcDaoSupport { - @Autowired - private PasswordEncoder passwordEncoder; - - @Autowired - private String appVersion; - - @Autowired - private PersistenceDao clusterDao; - - @Autowired - ServletContext servletContext; - - private static final String SCRIPT_DIR = "data/scripts/"; - - public void securePasswords() { - getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { - @Override - public void processRow(ResultSet rs) throws SQLException { - String username = rs.getString(1); - String password = rs.getString(2); - String encodedPassword = passwordEncoder.encodePassword(password, null); - getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); - logger.debug("Updating password for username: " + username); - } - }); - } - - private void executeScript(File script) { - ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); - int numOfExceptions; - try { - numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), new FileInputStream( - script), CoreConstants.ENCODING_UTF8, sqlOut, CoreConstants.ENCODING_UTF8); - String output = sqlOut.toString(); - sqlOut.close(); - logger.debug("Data script [" + script.getName() + "] returned with exit status [" + numOfExceptions - + "] and output [" + output + "]"); - if (numOfExceptions != 0) { - throw new GlusterRuntimeException("Server data initialization script [ " + script.getName() - + "] failed with [" + numOfExceptions + "] exceptions! [" + output + "]"); - } - } catch (Exception ex) { - throw new GlusterRuntimeException("Server data initialization script [" + script.getName() + "] failed!", - ex); - } - } - - private void initDatabase() { - logger.info("Initializing server data..."); - executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + appVersion)); - - securePasswords(); // encrypt the passwords - } - - private File getDirFromRelativePath(String relativePath) { - String scriptDirPath = servletContext.getRealPath(relativePath); - File scriptDir = new File(scriptDirPath); - return scriptDir; - } - - private void executeScriptsFrom(File scriptDir) { - if (!scriptDir.exists()) { - throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] doesn't exist!"); - } - - List scripts = Arrays.asList(scriptDir.listFiles()); - if(scripts.size() == 0) { - throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] is empty!"); - } - - Collections.sort(scripts); - for (File script : scripts) { - executeScript(script); - } - } - - /** - * Initializes the server database, if running for the first time. - */ - public synchronized void initServer() { - try { - String dbVersion = getDBVersion(); - if (!appVersion.equals(dbVersion)) { - logger.info("App version [" + appVersion + "] differs from data version [" + dbVersion - + "]. Trying to upgrade data..."); - upgradeData(dbVersion, appVersion); - } - } catch (Exception ex) { - logger.info("No cluster created yet. DB version query failed with error [" + ex.getMessage() + "]", ex); - // Database not created yet. Create it! - initDatabase(); - } - - // For development time debugging. To be removed later. - List clusters = clusterDao.findAll(); - logger.info(clusters.size()); - - if (clusters.size() > 0) { - for (ClusterInfo cluster : clusters) { - logger.info("Cluster: [" + cluster.getId() + "][" + cluster.getName() + "]"); - } - } else { - - } - } - - private void upgradeData(String fromVersion, String toVersion) { - executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + fromVersion + "-" + toVersion)); - } - - private String getDBVersion() { - return (String) clusterDao.getSingleResultFromSQL("select version from version"); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java deleted file mode 100644 index 4f168d66..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/InitializeDiskTask.java +++ /dev/null @@ -1,168 +0,0 @@ -/** - * InitializeDiskTask.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.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.constants.GlusterConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.core.util.Base64; - -public class InitializeDiskTask extends Task { - - private static final String INITIALIZE_DISK_SCRIPT = "format_device.py"; - - private String serverName; - private String diskName; - private String fsType; - private SshUtil sshUtil; - private GlusterUtil glusterUtil; - - public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, String fsType) { - super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" - + diskName, false, false, false); - - setServerName(serverName); - setDiskName(diskName); - setFsType(fsType); - taskInfo.setName(getId()); - init(); - } - - public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { - super(clusterService, clusterName, info); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - glusterUtil = ctx.getBean(GlusterUtil.class); - sshUtil = ctx.getBean(SshUtil.class); - } - - @Override - public String getId() { - return new String( - Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); - } - - @Override - public void resume() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void stop() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void pause() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void commit() { - // TODO Auto-generated method stub - } - - @Override - public TASK_TYPE getType() { - return TASK_TYPE.DISK_FORMAT; - } - - - @Override - public void start() { - try { - startInitializeDisk(serverName); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - } - } - - private void startInitializeDisk(String serverName) { - String fsTypeCommand = (getFsType().equals(GlusterConstants.FSTYPE_DEFAULT)) ? "" : " -t " + getFsType(); - ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_SCRIPT + fsTypeCommand + " " - + getDiskName()); - if (processResult.isSuccess()) { - TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput())); - taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); - getTaskInfo().setStatus(taskStatus); - return; - } - - // if we reach here, it means Initialize disk start failed. - throw new GlusterRuntimeException(processResult.toString()); - } - - @Override - public TaskStatus checkStatus() { - - try { - return glusterUtil.getInitializingDeviceStatus(serverName, getDiskName()); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); - } - } - - public void setDiskName(String diskName) { - this.diskName = diskName; - } - - public String getDiskName() { - return diskName; - } - - public void setServerName(String serverName) { - this.serverName = serverName; - } - - public String getServerName() { - return serverName; - } - - public void setFsType(String fsType) { - this.fsType = fsType; - } - - public String getFsType() { - return fsType; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java deleted file mode 100644 index 8ca15fc9..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/MigrateBrickTask.java +++ /dev/null @@ -1,227 +0,0 @@ -/** - * MigrateDiskTask.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.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.sun.jersey.core.util.Base64; - -public class MigrateBrickTask extends Task { - - private String fromBrick; - private String toBrick; - private Boolean autoCommit; - private GlusterUtil glusterUtil; - - public String getFromBrick() { - return fromBrick; - } - - public void setFromBrick(String fromBrick) { - this.fromBrick = fromBrick; - } - - public String getToBrick() { - return toBrick; - } - - public void setToBrick(String toBrick) { - this.toBrick = toBrick; - } - - public Boolean getAutoCommit() { - return autoCommit; - } - - public void setAutoCommit(Boolean autoCommit) { - this.autoCommit = autoCommit; - } - - public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, - String toBrick) { - super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" - + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); - setFromBrick(fromBrick); - setToBrick(toBrick); - taskInfo.setName(getId()); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - glusterUtil = ctx.getBean(GlusterUtil.class); - } - - @Override - public String getId() { - return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" - + toBrick)); - } - - @Override - public void start() { - try { - startMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone Offline. try with a new one. - startMigration(getNewOnlineServer().getName()); - } - } - - private void startMigration(String onlineServerName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServerName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "start"); - if (processResult.getOutput().trim().matches(".*started successfully$")) { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); - return; - } - } - - @Override - public void pause() { - try { - pauseMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - pauseMigration(getNewOnlineServer().getName()); - } - } - - private void pauseMigration(String onlineServer) { - ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServer, taskInfo.getReference(), - getFromBrick(), getToBrick(), "pause"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.getOutput().trim().matches(".*paused successfully$")) { - taskStatus.setCode(Status.STATUS_CODE_PAUSE); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - return; - } - } - - @Override - public void resume() { - start(); - } - - @Override - public void commit() { - try { - commitMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - commitMigration(getNewOnlineServer().getName()); - } - } - - private void commitMigration(String serverName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "commit"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*commit successful$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - } - } - } - - @Override - public void stop() { - try { - stopMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - stopMigration(getNewOnlineServer().getName()); - } - } - - private void stopMigration(String serverName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, taskInfo.getReference(), getFromBrick(), - getToBrick(), "abort"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.getOutput().trim().matches(".*aborted successfully$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - } - } - - @Override - public TaskStatus checkStatus() { - try { - return checkMigrationStatus(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - return checkMigrationStatus(getNewOnlineServer().getName()); - } - } - - private TaskStatus checkMigrationStatus(String serverName) { - if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE) { - return getTaskInfo().getStatus(); - } - // For committed task, status command (CLI) is invalid, just return current status - if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { - return getTaskInfo().getStatus(); - } - - - TaskStatus taskStatus = new TaskStatus(); - try { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "status"); - if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$") - || processResult.getOutput().trim().matches("^Number of files migrated = 0 .*Current file=")) { - // Note: Workaround - if no file in the volume brick to migrate, Gluster CLI is not giving proper - // (complete) status - taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); - if (autoCommit) { - commitMigration(serverName); - return getTaskInfo().getStatus(); // return the committed status - } else { - taskStatus.setMessage(processResult.getOutput().trim() - .replaceAll("Migration complete", "Commit pending")); - } - } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - taskStatus.setMessage(processResult.getOutput()); - } catch (Exception e) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - taskStatus.setMessage(e.getMessage()); - } - taskInfo.setStatus(taskStatus); // Update the task status - return taskStatus; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java deleted file mode 100644 index 24c2f1b5..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/RebalanceVolumeTask.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * RebalanceVolumeTask.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.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.utils.GlusterUtil; -import com.gluster.storage.management.server.utils.SshUtil; -import com.sun.jersey.core.util.Base64; - -public class RebalanceVolumeTask extends Task { - - private String layout; - private String serverName; - private SshUtil sshUtil; - private GlusterUtil glusterUtil; - - public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { - super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName - + " Rebalance", false, true, false); - setLayout(layout); - taskInfo.setName(getId()); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - sshUtil = ctx.getBean(SshUtil.class); - glusterUtil = ctx.getBean(GlusterUtil.class); - } - - @Override - public String getId() { - return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); - } - - @Override - public void start() { - try { - serverName = getOnlineServer().getName(); - startRebalance(serverName); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one - serverName = getNewOnlineServer().getName(); - startRebalance(serverName); - } - } - - private void startRebalance(String serverName) { - String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - if (processResult.isSuccess()) { - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); - return; - } - - // if we reach here, it means rebalance start failed. - throw new GlusterRuntimeException(processResult.toString()); - } - - @Override - public void resume() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Pause/Resume is not supported in Volume Rebalance"))); - } - - @Override - public void stop() { - try { - glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); - } catch (ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - } - } - - @Override - public void pause() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Pause/Resume is not supported in Volume Rebalance"))); - } - - @Override - public TaskStatus checkStatus() { - try { - return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - return getTaskInfo().getStatus(); - } - } - - public void setLayout(String layout) { - this.layout = layout; - } - - public String getLayout() { - return layout; - } - - @Override - public void commit() { - // TODO Auto-generated method stub - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java deleted file mode 100644 index feb02354..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/ServerSyncTask.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * ServerDiscoveryTask.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.tasks; - -import java.util.ArrayList; -import java.util.List; - -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.GlusterConstants; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.utils.GlusterCoreUtil; -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.data.ServerInfo; -import com.gluster.storage.management.server.resources.v1_0.DiscoveredServersResource; -import com.gluster.storage.management.server.services.ClusterService; -import com.gluster.storage.management.server.services.GlusterServerService; -import com.gluster.storage.management.server.utils.ServerUtil; - -/** - * Task for syncing server details. This performs two things:
- * 1. Auto-discovery of servers eligible to be added to the Gluster cluster.
- * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user - * adds/removes servers manually using the CLI. - */ -@Component -public class ServerSyncTask { - private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; - - @Autowired - private ServerUtil serverUtil; - - @Autowired - private DiscoveredServersResource discoveredServersResource; - - @Autowired - private GlusterServerService glusterServerService; - - @Autowired - private String discoveryMechanism; - - @Autowired - private ClusterService clusterService; - - @Autowired - private PersistenceDao clusterDao; - - public void perform() { - discoverServers(); - syncClusterServerMapping(); - } - - private void syncClusterServerMapping() { - List clusters = clusterService.getAllClusters(); - for(ClusterInfo cluster : clusters) { - List servers = cluster.getServers(); - List actualServers = glusterServerService.getGlusterServers(cluster.getName(), false); - updateRemovedServers(cluster, servers, actualServers); - updateAddedServers(cluster, servers, actualServers); - } - } - - private void updateAddedServers(ClusterInfo cluster, List servers, List actualServers) { - List addedServers = findAddedServers(cluster.getName(), servers, actualServers); - for(String addedServer : addedServers) { - clusterService.mapServerToCluster(cluster.getName(), addedServer); - } - } - - private void updateRemovedServers(ClusterInfo cluster, List servers, List actualServers) { - List removedServers = findRemovedServers(servers, actualServers); - for(String removedServer : removedServers) { - clusterService.unmapServerFromCluster(cluster.getName(), removedServer); - } - } - - private List findRemovedServers(List servers, List actualServers) { - List removedServers = new ArrayList(); - - for(ServerInfo server : servers) { - if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { - removedServers.add(server.getName()); - } - } - return removedServers; - } - - private List findAddedServers(String clusterName, List servers, List actualServers) { - List addedServers = new ArrayList(); - for(GlusterServer actualServer : actualServers) { - if(!serverExists(servers, actualServer.getName())) { - addedServers.add(actualServer.getName()); - } - } - return addedServers; - } - - private boolean serverExists(List servers, String name) { - for(ServerInfo server : servers) { - if(server.getName().equalsIgnoreCase(name)) { - return true; - } - } - return false; - } - - @SuppressWarnings("unchecked") - private void discoverServers() { - if(discoveryMechanism.equals(GlusterConstants.NONE)) { - return; - } - - List serverNameList = new ArrayList(); - - ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList()); - if(result.isSuccess()) { - List existingServers = clusterDao.findBySQL("select name from server_info"); - String serverNames = result.getOutput(); - String[] parts = serverNames.split(CoreConstants.NEWLINE); - for(String serverName : parts) { - // The server discovery mechanism will return every server that has not been "peer probed". However we - // need to filter out those servers that are the "first" server of a new cluster, and hence are still - // not peer probed. - if(!existingServers.contains(serverName)) { - serverNameList.add(serverName); - } - } - } - - discoveredServersResource.setDiscoveredServerNames(serverNameList); - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java deleted file mode 100644 index 119f6297..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/tasks/Task.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Task.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.tasks; - -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.server.services.ClusterService; - -public abstract class Task { - public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; - - protected TaskInfo taskInfo; - protected String clusterName; - private ClusterService clusterService; - - public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, - boolean canPause, boolean canStop, boolean canCommit) { - TaskInfo taskInfo = new TaskInfo(); - taskInfo.setType(type); - taskInfo.setReference(reference); - taskInfo.setDescription(desc); - taskInfo.setPauseSupported(canPause); - taskInfo.setStopSupported(canStop); - taskInfo.setCommitSupported(canCommit); - - init(clusterService, clusterName, taskInfo); - - } - - public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { - init(clusterService, clusterName, taskInfo); - } - - private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { - this.clusterService = clusterService; - setClusterName(clusterName); - setTaskInfo(taskInfo); - } - - protected GlusterServer getOnlineServer() { - return clusterService.getOnlineServer(clusterName); - } - - protected GlusterServer getNewOnlineServer() { - return clusterService.getNewOnlineServer(clusterName); - } - - protected GlusterServer getNewOnlineServer(String exceptServerName) { - return clusterService.getNewOnlineServer(clusterName, exceptServerName); - } - - public String getTypeStr() { - return TASK_TYPE_STR[taskInfo.getType().ordinal()]; - } - - public TASK_TYPE getType() { - return getTaskInfo().getType(); - } - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public TaskInfo getTaskInfo() { - return taskInfo; - } - - public void setTaskInfo(TaskInfo info) { - this.taskInfo = info; - } - - public abstract String getId(); - - public abstract void start(); - - public abstract void resume(); - - public abstract void stop(); - - public abstract void pause(); - - public abstract void commit(); - - /** - * This method should check current status of the task and update it's taskInfo accordingly - */ - public abstract TaskStatus checkStatus(); -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java deleted file mode 100644 index 6f1226aa..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/AbstractStatsFactory.java +++ /dev/null @@ -1,168 +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.utils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; -import com.gluster.storage.management.core.model.Status; - -/** - * - */ -@Component -public abstract class AbstractStatsFactory implements StatsFactory { - @Autowired - protected ServerUtil serverUtil; - - private Logger logger = Logger.getLogger(AbstractStatsFactory.class); - - protected ServerStats getFirstOnlineServerStats(List serverNames, String period, - boolean removeServerOnError, boolean removeOnlineServer) { - for(int i = serverNames.size() - 1; i >= 0; i--) { - String serverName = serverNames.get(i); - try { - ServerStats stats = fetchStats(serverName, period); - if(removeOnlineServer) { - serverNames.remove(serverName); - } - return stats; - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); - if(removeServerOnError) { - serverNames.remove(serverName); - } - continue; - } - } - throw new GlusterRuntimeException("All servers offline!"); - } - - protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { - if(serverNames.isEmpty()) { - return; - } - - int rowCount = aggregatedStats.getMetadata().getRowCount(); - int columnCount = aggregatedStats.getMetadata().getLegend().size(); - int[][] dataCount = initDataCountArray(rowCount, columnCount); - - for (String serverName : serverNames) { - try { - // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch performance stats from server [" + serverName + "]!", e); - continue; - } - } - - averageAggregatedStats(aggregatedStats, dataCount); - } - - /** - * - * @param statsToBeAdded - * @param targetStats - * @param dataCount Each element of this matrix will be incremented for every valid element added - * @return - */ - protected List addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { - List serverStatsRows = statsToBeAdded.getRows(); - for (int rowNum = 0; rowNum < serverStatsRows.size() - && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { - ServerStatsRow row = serverStatsRows.get(rowNum); - List rowData = row.getUsageData(); - - List aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); - for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { - // Add the data - Double data = rowData.get(i); - if(!data.isNaN()) { - // data is available. add it. - aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); - // increment record count. this will be used for calculating average of aggregated data. - dataCount[rowNum][i]++; - } - } - } - return serverStatsRows; - } - - protected void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { - List rows = aggregatedStats.getRows(); - for(int rowNum = 0; rowNum < rows.size(); rowNum++) { - List data = rows.get(rowNum).getUsageData(); - for(int columnNum = 0; columnNum < data.size(); columnNum++) { - data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); - } - } - } - - protected int[][] initDataCountArray(int rowCount, int columnCount) { - int[][] dataCount = new int[rowCount][columnCount]; - // initialize all data counts to 1 - for(int rowNum = 0; rowNum < rowCount; rowNum++) { - for(int columnNum = 0; columnNum < columnCount; columnNum++) { - dataCount[rowNum][columnNum] = 1; - } - } - return dataCount; - } - - @Override - public ServerStats fetchAggregatedStats(List serverNames, String period) { - if(serverNames == null || serverNames.size() == 0) { - throw new GlusterRuntimeException("No server names passed to fetchAggregaredStats!"); - } - - ServerStats firstServerStats = getFirstOnlineServerStats(serverNames, period, true, true); - - ServerStats aggregatedStats = new ServerStats(firstServerStats); - aggregateStats(serverNames, aggregatedStats, period); - return aggregatedStats; - } - - @Override - public ServerStats fetchStats(String serverName, String period, String...args) { - String argsStr = ""; - for (String arg : args) { - if(arg != null) { - argsStr += " " + arg; - } - } - Object output = serverUtil.executeOnServer(true, serverName, getStatsScriptName() + argsStr + " " + period, ServerStats.class); - //String cpuUsageData = " 1310468100 300 1310471700 13 3 user system total 13104681002.23802952e-14.3747778209e-016.6128073384e-01 13104684002.3387347338e-014.4642717442e-016.8030064780e-01 13104687005.5043873220e+006.2462376636e+001.1750624986e+01 13104690002.4350593653e+012.6214585217e+015.0565178869e+01 13104693004.0786489953e+014.6784713828e+018.7571203781e+01 13104696004.1459955508e+015.2546309044e+019.4006264551e+01 13104699004.2312286165e+015.2390588332e+019.4702874497e+01 13104702004.2603794982e+015.1598861493e+019.4202656475e+01 13104705003.8238751290e+014.5312089966e+018.3550841256e+01 13104708001.7949961224e+012.1282058418e+013.9232019642e+01 13104711001.2330371421e-014.6347832868e-015.8678204289e-01 13104714001.6313260492e-015.4088119561e-017.0401380052e-01 1310471700NaNNaNNaN "; - //Object output = unmarshal(ServerStats.class, cpuUsageData, false); - if(output instanceof Status) { - throw new GlusterRuntimeException(((Status)output).toString()); - } - return (ServerStats) output; - } - - public abstract String getStatsScriptName(); -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java deleted file mode 100644 index 27e271e5..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/CpuStatsFactory.java +++ /dev/null @@ -1,36 +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.utils; - -import org.springframework.stereotype.Component; - -/** - * - */ -@Component -public class CpuStatsFactory extends AbstractStatsFactory { - - private static final String CPU_STATS_SCRIPT = "get_rrd_cpu_details.py"; - - @Override - public String getStatsScriptName() { - return CPU_STATS_SCRIPT; - } - -} 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 deleted file mode 100644 index f5d09ac2..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/GlusterUtil.java +++ /dev/null @@ -1,664 +0,0 @@ -/** - * GlusterUtil.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.utils; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Pattern; - -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.GlusterConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.InitDiskStatusResponse; -import com.gluster.storage.management.core.model.InitDiskStatusResponse.FORMAT_STATUS; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; -import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; -import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; -import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; -import com.gluster.storage.management.core.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.v1_0.TasksResource; -import com.sun.jersey.api.core.InjectParam; - -@Component -public class GlusterUtil { - private static final String glusterFSminVersion = "3.1"; - - private static final String HOSTNAME_PFX = "Hostname:"; - private static final String UUID_PFX = "Uuid:"; - private static final String STATE_PFX = "State:"; - private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; - - private static final String VOLUME_NAME_PFX = "Volume Name:"; - private static final String VOLUME_TYPE_PFX = "Type:"; - private static final String VOLUME_STATUS_PFX = "Status:"; - private static final String VOLUME_NUMBER_OF_BRICKS = "Number of Bricks:"; - private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; - private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; - private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; - private static final String VOLUME_OPTION_AUTH_ALLOW_PFX = "auth.allow:"; - private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; - private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; - private static final String VOLUME_TYPE_REPLICATE = "Replicate"; - private static final String GLUSTERD_INFO_FILE = "/etc/glusterd/glusterd.info"; - - private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); - - private static final String INITIALIZE_DISK_STATUS_SCRIPT = "get_format_device_status.py"; - - @Autowired - private SshUtil sshUtil; - - @Autowired - private ServerUtil serverUtil; - - @Autowired - private TasksResource taskResource; - - public void setSshUtil(SshUtil sshUtil) { - this.sshUtil = sshUtil; - } - - public SshUtil getSshUtil() { - return sshUtil; - } - - /** - * Extract value of given token from given line. It is assumed that the token, if present, will be of the following - * form: token: value - * - * @param line - * Line to be analyzed - * @param token - * Token whose value is to be extracted - * @return Value of the token, if present in the line - */ - private final String extractToken(String line, String token) { - if (line.contains(token)) { - return line.split(token)[1].trim(); - } - return null; - } - - public GlusterServer getGlusterServer(GlusterServer onlineServer, String serverName) { - List servers = getGlusterServers(onlineServer); - for (GlusterServer server : servers) { - if (server.getName().equals(serverName)) { - return server; - } - } - return null; - } - - private String getUuid(String serverName) { - ProcessResult result = getSshUtil().executeRemote(serverName, "cat " + GLUSTERD_INFO_FILE); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't read file [" + GLUSTERD_INFO_FILE + "]. Error: " - + result.toString()); - } - return result.getOutput().split("=")[1]; - } - - public List getGlusterServers(GlusterServer knownServer) { - String output = getPeerStatus(knownServer.getName()); - if (output == null) { - return null; - } - - knownServer.setUuid(getUuid(knownServer.getName())); - - List glusterServers = new ArrayList(); - glusterServers.add(knownServer); - - GlusterServer server = null; - boolean foundHost = false; - boolean foundUuid = false; - for (String line : output.split(CoreConstants.NEWLINE)) { - if (foundHost && foundUuid) { - // Host and UUID is found, we should look for state - String state = extractToken(line, STATE_PFX); - if (state != null) { - server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE - : SERVER_STATUS.OFFLINE); - // Completed populating current server. Add it to the list - // and reset all related variables. - glusterServers.add(server); - - foundHost = false; - foundUuid = false; - server = null; - } - } else if (foundHost) { - // Host is found, look for UUID - String uuid = extractToken(line, UUID_PFX); - if (uuid != null) { - server.setUuid(uuid); - foundUuid = true; - } - } else { - // Look for the next host - if (server == null) { - server = new GlusterServer(); - } - String hostName = extractToken(line, HOSTNAME_PFX); - if (hostName != null) { - server.setName(hostName); - foundHost = true; - } - } - - } - return glusterServers; - } - - public List getGlusterServerNames(String knownServer) { - String output = getPeerStatus(knownServer); - if (output == null) { - return null; - } - - List glusterServerNames = new ArrayList(); - for (String line : output.split(CoreConstants.NEWLINE)) { - String hostName = extractToken(line, HOSTNAME_PFX); - if (hostName != null) { - glusterServerNames.add(hostName); - } - } - return glusterServerNames; - } - - /** - * @param knownServer - * A known server on which the gluster command will be executed to fetch peer status - * @return Outout of the "gluster peer status" command - */ - private String getPeerStatus(String knownServer) { - String output; - ProcessResult result = getSshUtil().executeRemote(knownServer, "gluster peer status"); - if (!result.isSuccess()) { - output = null; - } - output = result.getOutput(); - return output; - } - - public void addServer(String existingServer, String newServer) { - ProcessResult result = sshUtil.executeRemote(existingServer, "gluster peer probe " + newServer); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't probe server [" + newServer + "] from [" + existingServer - + "]. Error: " + result); - } - - // reverse peer probe to ensure that host names appear in peer status on both sides - result = sshUtil.executeRemote(newServer, "gluster peer probe " + existingServer); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't _reverse_ probe server [" + existingServer + "] from [" - + newServer + "]. Error: " + result); - } - } - - public Status startVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster volume start " + volumeName)); - } - - public Status stopVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume stop " + volumeName)); - } - - public void resetOptions(String volumeName, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't reset options for volume [" + volumeName + "]! Error: " - + result); - } - } - - public void createVolume(String knownServer, String volumeName, String volumeTypeStr, String transportTypeStr, - Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, String options) { - - int count = 1; // replica or stripe count - - VOLUME_TYPE volType = Volume.getVolumeTypeByStr(volumeTypeStr); - String volTypeArg = null; - if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - volTypeArg = "replica"; - count = replicaCount; - } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - volTypeArg = "stripe"; - count = stripeCount; - } - - String transportTypeArg = null; - TRANSPORT_TYPE transportType = Volume.getTransportTypeByStr(transportTypeStr); - transportTypeArg = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; - - String command = prepareVolumeCreateCommand(volumeName, StringUtil.extractList(bricks, ","), count, - volTypeArg, transportTypeArg); - ProcessResult result = sshUtil.executeRemote(knownServer, command); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Error in creating volume [" + volumeName + "]: " + result); - } - - try { - createOptions(volumeName, StringUtil.extractMap(options, ",", "="), knownServer); - } catch(Exception e) { - throw new GlusterRuntimeException( - "Volume created successfully, however following errors occurred while setting options: " - + CoreConstants.NEWLINE + e.getMessage()); - } - } - - private String prepareVolumeCreateCommand(String volumeName, List brickDirectories, int count, - String volumeType, String transportTypeStr) { - StringBuilder command = new StringBuilder("gluster volume create " + volumeName + " "); - if (volumeType != null) { - command.append(volumeType + " " + count + " "); - } - command.append("transport " + transportTypeStr); - for (String brickDir : brickDirectories) { - command.append(" " + brickDir); - } - return command.toString(); - } - - public void createOptions(String volumeName, Map options, String knownServer) { - String errors = ""; - if (options != null) { - for (Entry option : options.entrySet()) { - String key = option.getKey(); - String value = option.getValue(); - - try { - setOption(volumeName, key, value, knownServer); - } catch(Exception e) { - // append error - errors += e.getMessage() + CoreConstants.NEWLINE; - } - } - } - if (!errors.trim().isEmpty()) { - throw new GlusterRuntimeException("Errors while setting option(s) on volume [" + volumeName + "] : " - + errors.trim()); - } - } - - public void setOption(String volumeName, String key, String value, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " - + "\"" + value + "\""); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Volume [" + volumeName + "] set [" + key + "=" + value + "] => " - + result); - } - } - - public Status deleteVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume delete " + volumeName)); - } - - private String getVolumeInfo(String volumeName, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info " + volumeName); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [gluster volume info " + volumeName + "] failed on [" - + knownServer + "] with error: " + result); - } - return result.getOutput(); - } - - private String getVolumeInfo(String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info "); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [gluster volume info] failed on [" + knownServer - + "] with error: " + result); - } - return result.getOutput(); - } - - private boolean readVolumeType(Volume volume, String line) { - String volumeType = extractToken(line, VOLUME_TYPE_PFX); - if (volumeType != null) { - if (volumeType.equals(VOLUME_TYPE_DISTRIBUTE)) { - volume.setVolumeType(VOLUME_TYPE.PLAIN_DISTRIBUTE); - } else if (volumeType.equals(VOLUME_TYPE_REPLICATE)) { - volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_MIRROR); - volume.setReplicaCount(Volume.DEFAULT_REPLICA_COUNT); - } else { - volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_STRIPE); - volume.setStripeCount(Volume.DEFAULT_STRIPE_COUNT); - } - return true; - } - return false; - } - - private void readReplicaOrStripeCount(Volume volume, String line) { - if (extractToken(line, "x") != null) { - // expected formated of line is "Number of Bricks: 3 x 2 = 6" - int count = Integer.parseInt(line.split("x")[1].split("=")[0].trim()); - if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - volume.setStripeCount(count); - } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - volume.setReplicaCount(count); - volume.setStripeCount(0); - } - - } - return; - } - - private boolean readVolumeStatus(Volume volume, String line) { - String volumeStatus = extractToken(line, VOLUME_STATUS_PFX); - if (volumeStatus != null) { - volume.setStatus(volumeStatus.equals("Started") ? VOLUME_STATUS.ONLINE : VOLUME_STATUS.OFFLINE); - return true; - } - return false; - } - - private boolean readTransportType(Volume volume, String line) { - String transportType = extractToken(line, VOLUME_TRANSPORT_TYPE_PFX); - if (transportType != null) { - volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET : TRANSPORT_TYPE.INFINIBAND); - return true; - } - return false; - } - - private boolean readBrick(Volume volume, String brickLine) { - BRICK_STATUS brickStatus; - if (brickLine.matches("Brick[0-9]+:.*")) { - // line: "Brick1: server1:/export/md0/volume-name" - String brickName = brickLine.split(": ")[1]; - String[] brickParts = brickLine.split(":"); - String serverName = brickParts[1].trim(); - String brickDir = brickParts[2].trim(); - //To get the brick status - brickStatus = getBrickStatus(serverName, volume.getName(), brickName); - - addBrickToVolume(volume, serverName, brickDir, brickStatus); - return true; - } - return false; - } - - private void addBrickToVolume(Volume volume, String serverName, String brickDir, BRICK_STATUS status) { - //If brick directory has standard path, find and assign device name otherwise null - String stdBrickDirPattern = "^/export/.*/.*"; // e.g: /export/sdb/test - String deviceName = null; - if (Pattern.matches(stdBrickDirPattern, brickDir) ) { - deviceName = brickDir.split("/")[2].trim(); - } - volume.addBrick(new Brick(serverName, status, deviceName, brickDir)); - } - - // Do not throw exception, Gracefully handle as Offline brick. - private BRICK_STATUS getBrickStatus(String serverName, String volumeName, String brick){ - try { - ProcessResult output = getSshUtil().executeRemote(serverName, "get_brick_status.py" + " " + volumeName + " " + brick); - - if (output.isSuccess() && output.getOutput().equals(CoreConstants.ONLINE)) { - return BRICK_STATUS.ONLINE; - } else { - return BRICK_STATUS.OFFLINE; - } - } catch(Exception e) { // Particularly interested on ConnectionExecption, if the server is offline - return BRICK_STATUS.OFFLINE; - } - } - - private boolean readBrickGroup(String line) { - return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; - } - - private boolean readOptionReconfigGroup(String line) { - return extractToken(line, VOLUME_OPTIONS_RECONFIG_PFX) != null; - } - - private boolean readOption(Volume volume, String line) { - if (line.matches("^[^:]*:.*$")) { - int index = line.indexOf(':'); - volume.setOption(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim()); - - if (line.substring(0, index).trim().equals(Volume.OPTION_NFS_DISABLE)) { - if (line.substring(index + 1, line.length()).trim().equals(GlusterConstants.ON)) { - volume.disableNFS(); - } else { - volume.enableNFS(); - } - } - - return true; - } - return false; - } - - public Volume getVolume(String volumeName, String knownServer) { - return parseVolumeInfo(getVolumeInfo(volumeName, knownServer)).get(0); - } - - public List getAllVolumes(String knownServer) { - return parseVolumeInfo(getVolumeInfo(knownServer)); - } - - private List parseVolumeInfo(String volumeInfoText) { - List volumes = new ArrayList(); - boolean isBricksGroupFound = false; - boolean isOptionReconfigFound = false; - Volume volume = null; - - for (String line : volumeInfoText.split(CoreConstants.NEWLINE)) { - String volumeName = extractToken(line, VOLUME_NAME_PFX); - if (volumeName != null) { - if (volume != null) { - volumes.add(volume); - } - - // prepare next volume to be read - volume = new Volume(); - volume.setName(volumeName); - isBricksGroupFound = isOptionReconfigFound = false; - continue; - } - - if (readVolumeType(volume, line)) - continue; - if (extractToken(line, VOLUME_NUMBER_OF_BRICKS) != null) { - readReplicaOrStripeCount(volume, line); - } - if (readVolumeStatus(volume, line)) - continue; - if (readTransportType(volume, line)) - continue; - if (readBrickGroup(line)) { - isBricksGroupFound = true; - continue; - } - - if (isBricksGroupFound) { - if (readBrick(volume, line)) { - continue; - } else { - isBricksGroupFound = false; - } - } - - if (readOptionReconfigGroup(line)) { - isOptionReconfigFound = true; - continue; - } - - if (isOptionReconfigFound) { - if (readOption(volume, line)) { - continue; - } else { - isOptionReconfigFound = false; - } - } - } - - if (volume != null) {// Adding the last volume parsed - volumes.add(volume); - } - - return volumes; - } - - public void addBricks(String volumeName, List bricks, String knownServer) { - StringBuilder command = new StringBuilder("gluster volume add-brick " + volumeName); - for (String brickDir : bricks) { - command.append(" " + brickDir); - } - - ProcessResult result = sshUtil.executeRemote(knownServer, command.toString()); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Error in volume [" + volumeName + "] add-brick [" + bricks + "]: " - + result); - } - } - - public String getLogLocation(String volumeName, String brickName, String knownServer) { - String command = "gluster volume log locate " + volumeName + " " + brickName; - ProcessResult result = sshUtil.executeRemote(knownServer, command); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [" + command + "] failed with error: [" + result.getExitValue() - + "][" + result.getOutput() + "]"); - } - String output = result.getOutput(); - if (output.startsWith(VOLUME_LOG_LOCATION_PFX)) { - return output.substring(VOLUME_LOG_LOCATION_PFX.length()).trim(); - } - - throw new GlusterRuntimeException("Couldn't parse output of command [" + command + "]. Output [" + output - + "] doesn't start with prefix [" + VOLUME_LOG_LOCATION_PFX + "]"); - } - - public String getLogFileNameForBrickDir(String brickDir) { - String logFileName = brickDir; - if (logFileName.startsWith(File.separator)) { - logFileName = logFileName.replaceFirst(File.separator, ""); - } - logFileName = logFileName.replaceAll(File.separator, "-") + ".log"; - return logFileName; - } - - public Status removeBricks(String volumeName, List bricks, String knownServer) { - StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName); - for (String brickDir : bricks) { - command.append(" " + brickDir); - } - return new Status(sshUtil.executeRemote(knownServer, command.toString())); - } - - public void removeServer(String existingServer, String serverName) { - ProcessResult result = sshUtil.executeRemote(existingServer, "gluster --mode=script peer detach " + serverName); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); - } - } - - public TaskStatus checkRebalanceStatus(String serverName, String volumeName) { - String command = "gluster volume rebalance " + volumeName + " status"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches("^rebalance completed.*")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else if(processResult.getOutput().trim().matches(".*in progress.*")) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - taskStatus.setMessage(processResult.getOutput()); // Common - return taskStatus; - } - - public void stopRebalance(String serverName, String volumeName) { - String command = "gluster volume rebalance " + volumeName + " stop"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - } - } - - public TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { - Object response = serverUtil.executeOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + diskName, - InitDiskStatusResponse.class); - - TaskStatus taskStatus = new TaskStatus(); - if (response instanceof Status) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - taskStatus.setMessage(((Status) response).getMessage()); - throw new GlusterRuntimeException(((Status) response).getMessage()); - } - - InitDiskStatusResponse initDiskStatusResponse = (InitDiskStatusResponse) response; - - if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.COMPLETED) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.IN_PROGRESS) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - taskStatus.setPercentCompleted(Math.round(initDiskStatusResponse.getCompletedBlocks() - / initDiskStatusResponse.getTotalBlocks() * 100)); - } else if(initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.NOT_RUNNING) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - - taskStatus.setMessage(initDiskStatusResponse.getMessage()); - return taskStatus; - } - - public ProcessResult executeBrickMigration(String onlineServerName, String volumeName, String fromBrick, - String toBrick, String operation) { - String command = "gluster volume replace-brick " + volumeName + " " + fromBrick + " " + toBrick + " " + operation; - ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); - if (!processResult.isSuccess()) { - throw new GlusterRuntimeException(processResult.toString()); - } - return processResult; - } - - public static void main(String args[]) { - // List names = new GlusterUtil().getGlusterServerNames(); - // System.out.println(names); - List disks = new ArrayList(); - disks.add("server1:sda"); - disks.add("server1:sdb"); - new GlusterUtil().addBricks("Volume3", disks, "localhost"); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java deleted file mode 100644 index fcbf43d5..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/MemoryStatsFactory.java +++ /dev/null @@ -1,68 +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.utils; - -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; - -/** - * - */ -@Component -public class MemoryStatsFactory extends AbstractStatsFactory { - - private static final String MEM_STATS_SCRIPT = "get_rrd_memory_details.py"; - - @Override - public String getStatsScriptName() { - return MEM_STATS_SCRIPT; - } - - @Override - public ServerStats fetchStats(String serverName, String period, String... args) { - ServerStats stats = super.fetchStats(serverName, period, args); - - // stats returned by rrd script contains five columns - user, free, cache, buffer, total - // out of this, the "user" memory includes cached and buffer. We remove them to get the - // actual memory used by "user" - for(ServerStatsRow row : stats.getRows()) { - List data = row.getUsageData(); - Double user = data.get(0); - Double free = data.get(1); - Double cache = data.get(2); - Double buffer = data.get(3); - Double total = data.get(4); - - Double actualUser = user - cache - buffer; - - // convert all figures from bytes to percentages - data.set(0, (actualUser * 100) / total); - data.set(1, (free * 100) / total); - data.set(2, (cache * 100) / total); - data.set(3, (buffer * 100) / total); - data.set(4, (total * 100) / total); - } - - return stats; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java deleted file mode 100644 index 2a50d598..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/NetworkStatsFactory.java +++ /dev/null @@ -1,123 +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.utils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.NetworkInterface; -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; - -/** - * - */ -@Component -public class NetworkStatsFactory extends AbstractStatsFactory { - private static final Logger logger = Logger.getLogger(NetworkStatsFactory.class); - private static final String NETWORK_STATS_SCRIPT = "get_rrd_net_details.py"; - private int[][] dataCount; - - @Override - public String getStatsScriptName() { - return NETWORK_STATS_SCRIPT; - } - - @Override - protected ServerStats getFirstOnlineServerStats(List serverNames, String period, - boolean removeServerOnError, boolean removeOnlineServer) { - ServerStats firstOnlineServerStats = null; - for(int i = serverNames.size() - 1; i >= 0; i--) { - String serverName = serverNames.get(i); - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - try { - for(NetworkInterface networkInterface : server.getNetworkInterfaces()) { - ServerStats stats = fetchStats(serverName, period, networkInterface.getName()); - if(firstOnlineServerStats == null) { - firstOnlineServerStats = stats; - int rowCount = firstOnlineServerStats.getMetadata().getRowCount(); - int columnCount = firstOnlineServerStats.getMetadata().getLegend().size(); - dataCount = initDataCountArray(rowCount, columnCount); - } else { - addServerStats(stats, firstOnlineServerStats, dataCount); - } - } - - if(removeOnlineServer) { - serverNames.remove(serverName); - } - return firstOnlineServerStats; - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); - if(removeServerOnError) { - serverNames.remove(serverName); - } - continue; - } - } - throw new GlusterRuntimeException("All servers offline!"); - } - - protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { - if(serverNames.isEmpty()) { - return; - } - - for (String serverName : serverNames) { - try { - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - - for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { - // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); - } - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); - continue; - } - } - - averageAggregatedStats(aggregatedStats, dataCount); - } - - @Override - public ServerStats fetchStats(String serverName, String period, String... args) { - ServerStats stats = super.fetchStats(serverName, period, args); - - // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s - int step = stats.getMetadata().getStep(); - for(ServerStatsRow row : stats.getRows()) { - List data = row.getUsageData(); - for (int i = 0; i < data.size(); i++) { - Double val = data.get(i); - data.set(i, val / 1024 / step); - } - } - - return stats; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java deleted file mode 100644 index f0aab567..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/ServerUtil.java +++ /dev/null @@ -1,258 +0,0 @@ -/** - * ServerUtil.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.utils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.response.GenericResponse; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.core.utils.ProcessUtil; - -@Component -public class ServerUtil { - @Autowired - ServletContext servletContext; - - @Autowired - private SshUtil sshUtil; - - private static final Logger logger = Logger.getLogger(ServerUtil.class); - - private static final String SCRIPT_DIR = "scripts"; - private static final String SCRIPT_COMMAND = "python"; - private static final String REMOTE_SCRIPT_GET_DISK_FOR_DIR = "get_disk_for_dir.py"; - private static final String REMOTE_SCRIPT_GET_SERVER_DETAILS = "get_server_details.py"; - - public void setSshUtil(SshUtil sshUtil) { - this.sshUtil = sshUtil; - } - - public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List arguments) { - List command = new ArrayList(); - - command.add(SCRIPT_COMMAND); - command.add(getScriptPath(scriptName)); - command.addAll(arguments); - return new ProcessUtil().executeCommand(runInForeground, command); - } - - private String getScriptPath(String scriptName) { - String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; - return scriptPath; - } - - /** - * Fetch details of the given server. The server name must be populated in the object before calling this method. - * - * @param server - * Server whose details are to be fetched - */ - public void fetchServerDetails(Server server) { - Object response = fetchServerDetails(server.getName()); - server.copyFrom((Server) response); // Update the details in object - server.setDisks(((Server) response).getDisks()); - } - - public String fetchHostName(String serverName) { - Object response = fetchServerDetails(serverName); - return ((Server) response).getName(); - } - - private Object fetchServerDetails(String serverName) { - // fetch standard server details like cpu, disk, memory details - Object response = executeOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); - if (response instanceof Status) { - throw new GlusterRuntimeException(((Status) response).getMessage()); - } - return response; - } - - /** - * Executes given command on given server - * - * @param runInForeground - * @param serverName - * @param commandWithArgs - * @param expectedClass - * Class of the object expected from script execution - * @return Object of the expected class from remote execution of the command. In case the remote execution fails - * ungracefully, an object of class {@link Status} will be returned. - */ - @SuppressWarnings("rawtypes") - public Object executeOnServer(boolean runInForeground, String serverName, String commandWithArgs, - Class expectedClass) { - try { - String output = executeOnServer(serverName, commandWithArgs); - - // In case the script execution exits ungracefully, the agent would return a GenericResponse. - // hence pass last argument as true to try GenericResponse unmarshalling in such cases. - Object response = unmarshal(expectedClass, output, expectedClass != GenericResponse.class); - if (expectedClass != GenericResponse.class && response instanceof GenericResponse) { - // expected class was not GenericResponse, but that's what we got. This means the - // script failed ungracefully. Extract and return the status object from the response - return ((GenericResponse) response).getStatus(); - } - return response; - } catch (RuntimeException e) { - // Except for connection exception, wrap any other exception in the a object and return it. - if (e instanceof ConnectionException) { - throw e; - } else { - // error during unmarshalling. return status with error from exception. - return new Status(e); - } - } - } - - private String executeOnServer(String serverName, String commandWithArgs) { - ProcessResult result = sshUtil.executeRemote(serverName, commandWithArgs); - - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [" + commandWithArgs + "] failed on [" + serverName - + "] with error [" + result.getExitValue() + "][" + result.getOutput() + "]"); - } - return result.getOutput(); - } - - // This is the old executeOnServer that used socket communication. - // We can keep it commented for the time being. - // private String executeOnServerUsingSocket(String serverName, String commandWithArgs) { - // try { - // InetAddress address = InetAddress.getByName(serverName); - // Socket connection = new Socket(address, 50000); - // - // PrintWriter writer = new PrintWriter(connection.getOutputStream(), true); - // writer.println(commandWithArgs); - // writer.println(); // empty line means end of request - // - // InputStream inputStream = connection.getInputStream(); - // int available = inputStream.available(); - // - // StringBuffer output = new StringBuffer(); - // if( available > 0 ) { - // // This happens when PeerAgent sends complete file - // byte[] responseData = new byte[available]; - // inputStream.read(responseData); - // output.append(new String(responseData, "UTF-8")); - // } else { - // // This happens in case of normal XML response from PeerAgent - // BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); - // - // String line; - // while (!(line = reader.readLine()).trim().isEmpty()) { - // output.append(line + CoreConstants.NEWLINE); - // } - // } - // connection.close(); - // - // return output.toString(); - // } catch (Exception e) { - // throw new GlusterRuntimeException("Error during remote execution: [" + e.getMessage() + "]"); - // } - // } - - public void getFileFromServer(String serverName, String remoteFileName, String localDirName) { - sshUtil.getFile(serverName, remoteFileName, localDirName); - } - - /** - * Unmarshals given input string into object of given class - * - * @param expectedClass - * Class whose object is expected - * @param input - * Input string - * @param tryGenericResponseOnFailure - * If true, and if the unmarshalling fails for given class, another unmarshalling will be attempted with - * class {@link GenericResponse}. If this also fails, a status object with exception message is created - * and returned. - * @return Object of given expected class, or a status object in case first unmarshalling fails. - */ - @SuppressWarnings("rawtypes") - private Object unmarshal(Class expectedClass, String input, boolean tryGenericResponseOnFailure) { - try { - // create JAXB context and instantiate marshaller - JAXBContext context = JAXBContext.newInstance(expectedClass); - Unmarshaller um = context.createUnmarshaller(); - return um.unmarshal(new ByteArrayInputStream(input.getBytes())); - } catch (JAXBException e) { - if (tryGenericResponseOnFailure) { - // unmarshalling failed. try to unmarshal a GenericResponse object - return unmarshal(GenericResponse.class, input, false); - - } - return new Status(Status.STATUS_CODE_FAILURE, "Error during unmarshalling string [" + input - + "] for class [" + expectedClass.getName() + ": [" + e.getMessage() + "]"); - } - } - - /** - * @param serverName - * Server on which the directory is present - * @param brickDir - * Directory whose disk is to be fetched - * @return Status object containing the disk name, or error message in case the remote script fails. - */ - public Status getDiskForDir(String serverName, String brickDir) { - return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); - } - - public static void main(String[] args) { -// ServerStats stats = new ServerUtil().fetchCPUUsageData("s1", "1d"); -// for(ServerStatsRow row : stats.getRows()) { -// System.out.println(row.getUsageData().get(2)); -// } -// JAXBContext context; -// try { -// context = JAXBContext.newInstance(ServerStats.class); -// Marshaller m = context.createMarshaller(); -// ByteArrayOutputStream out = new ByteArrayOutputStream(); -// m.marshal(stats, out); -// ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); -// for(ServerStatsRow row : stats1.getRows()) { -// System.out.println(row.getUsageData().get(2)); -// } -// } catch (JAXBException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java deleted file mode 100644 index bf82bc6c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/SshUtil.java +++ /dev/null @@ -1,388 +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.utils; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import ch.ethz.ssh2.ChannelCondition; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.SCPClient; -import ch.ethz.ssh2.Session; -import ch.ethz.ssh2.StreamGobbler; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.utils.FileUtil; -import com.gluster.storage.management.core.utils.LRUCache; -import com.gluster.storage.management.core.utils.ProcessResult; - -/** - * - */ -@Component -public class SshUtil { - private static final String TEMP_DIR = "/tmp/"; - public static final String SSH_AUTHORIZED_KEYS_DIR_LOCAL = "/opt/glustermg/keys/"; - public static final String SSH_AUTHORIZED_KEYS_DIR_REMOTE = "/root/.ssh/"; - private static final String SSH_AUTHORIZED_KEYS_FILE = "authorized_keys"; - private static final String SSH_AUTHORIZED_KEYS_PATH_REMOTE = SSH_AUTHORIZED_KEYS_DIR_REMOTE + SSH_AUTHORIZED_KEYS_FILE; - public static final File PRIVATE_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa"); - public static final File PUBLIC_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa.pub"); -// private static final String SCRIPT_DISABLE_SSH_PASSWORD_AUTH = "disable-ssh-password-auth.sh"; - private static final String PRIVATE_KEY_PASSPHRASE = "gluster"; - private LRUCache sshConnCache = new LRUCache(10); - - // TODO: Make user name configurable - private static final String USER_NAME = "root"; - // TODO: Make default password configurable - private static final String DEFAULT_PASSWORD = "syst3m"; - - private static final Logger logger = Logger.getLogger(SshUtil.class); - - @Autowired - private Integer sshConnectTimeout; - @Autowired - private Integer sshKexTimeout; - @Autowired - private Integer sshExecTimeout; - - public boolean hasDefaultPassword(String serverName) { - try { - getConnectionWithPassword(serverName); - return true; - } catch(ConnectionException e) { - return false; - } - } - - public boolean isPublicKeyInstalled(String serverName) { - try { - getConnection(serverName); - return true; - } catch(ConnectionException e) { - return false; - } - } - - public void getFile(String serverName, String remoteFile, String localDir) { - try { - Connection conn = getConnection(serverName); - SCPClient scpClient = new SCPClient(conn); - scpClient.get(remoteFile, localDir); - } catch (IOException e) { - throw new GlusterRuntimeException("Error while fetching file [" + remoteFile + "] from server [" - + serverName + "]", e); - } - } - - public synchronized void installPublicKey(String serverName) { - Connection conn = getConnectionWithPassword(serverName); - SCPClient scpClient = new SCPClient(conn); - - // delete file if it exists - File localTempFile = new File(TEMP_DIR + SSH_AUTHORIZED_KEYS_FILE); - if(localTempFile.exists()) { - localTempFile.delete(); - } - try { - // get authorized_keys from server - scpClient.get(SSH_AUTHORIZED_KEYS_PATH_REMOTE, TEMP_DIR); - } catch (IOException e) { - // file doesn't exist. it will get created. - } - - byte[] publicKeyData; - try { - publicKeyData = FileUtil.readFileAsByteArray(PUBLIC_KEY_FILE); - } catch (Exception e) { - throw new GlusterRuntimeException("Couldn't load public key file [" + PUBLIC_KEY_FILE + "]", e); - } - - try { - // append it - FileOutputStream outputStream = new FileOutputStream(localTempFile, true); - outputStream.write(CoreConstants.NEWLINE.getBytes()); - outputStream.write(publicKeyData); - outputStream.close(); - } catch (Exception e) { - throw new GlusterRuntimeException("Couldnt append file [" + localTempFile + "] with public key!", e); - } - - try { - scpClient.put(localTempFile.getAbsolutePath(), SSH_AUTHORIZED_KEYS_FILE, SSH_AUTHORIZED_KEYS_DIR_REMOTE, "0600"); - } catch (IOException e) { - throw new GlusterRuntimeException("Couldn't add public key to server [" + serverName + "]", e); - } - - // It was decided NOT to disable password login as this may not be acceptable in a bare-metal environment - // disableSshPasswordLogin(serverName, scpClient); - } - -// private void disableSshPasswordLogin(String serverName, SCPClient scpClient) { -// ProcessResult result = executeRemote(serverName, SCRIPT_DISABLE_SSH_PASSWORD_AUTH); -// if(!result.isSuccess()) { -// throw new GlusterRuntimeException("Couldn't disable SSH password authentication on [" + serverName -// + "]. Error: " + result); -// } -// } - - private Connection getConnectionWithPassword(String serverName) { - Connection conn = createConnection(serverName); - authenticateWithPassword(conn); - return conn; - } - - private synchronized Connection getConnection(String serverName) { - Connection conn = sshConnCache.get(serverName); - if (conn != null) { - return conn; - } - - conn = createConnection(serverName); - authenticateWithPublicKey(conn); - sshConnCache.put(serverName, conn); - return conn; - } - - private void authenticateWithPublicKey(Connection conn) { - try { - if (!supportsPublicKeyAuthentication(conn)) { - throw new ConnectionException("Public key authentication not supported on [" + conn.getHostname() - + "]"); - } - - if (!conn.authenticateWithPublicKey(USER_NAME, PRIVATE_KEY_FILE, PRIVATE_KEY_PASSPHRASE)) { - throw new ConnectionException("SSH Authentication (public key) failed for server [" - + conn.getHostname() + "]"); - } - } catch (IOException e) { - e.printStackTrace(); - throw new ConnectionException("Exception during SSH authentication (public key) for server [" - + conn.getHostname() + "]", e); - } - } - - private void authenticateWithPassword(Connection conn) { - try { - if (!supportsPasswordAuthentication(conn)) { - throw new ConnectionException("Password authentication not supported on [" + conn.getHostname() - + "]"); - } - - if (!conn.authenticateWithPassword(USER_NAME, DEFAULT_PASSWORD)) { - throw new ConnectionException("SSH Authentication (password) failed for server [" - + conn.getHostname() + "]"); - } - } catch (IOException e) { - e.printStackTrace(); - throw new ConnectionException("Exception during SSH authentication (password) for server [" - + conn.getHostname() + "]", e); - } - } - - private boolean supportsPasswordAuthentication(Connection conn) throws IOException { - return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("password"); - } - - private boolean supportsPublicKeyAuthentication(Connection conn) throws IOException { - return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("publickey"); - } - - private Connection createConnection(String serverName) { - Connection conn; - conn = new Connection(serverName); - try { - conn.connect(null, sshConnectTimeout, sshKexTimeout); - } catch (IOException e) { - logger.error("Couldn't establish SSH connection with server [" + serverName + "]", e); - throw new ConnectionException("Exception while creating SSH connection with server [" + serverName + "]", e); - } - return conn; - } - - private boolean wasTerminated(int condition) { - return ((condition | ChannelCondition.EXIT_SIGNAL) == condition); - } - - private boolean hasErrors(int condition, Session session) { - return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session))); - } - - private boolean timedOut(int condition) { - return (condition == ChannelCondition.TIMEOUT); - } - - private boolean exitedWithError(Session session) { - return session.getExitStatus() != ProcessResult.SUCCESS; - } - - private boolean exitedGracefully(int condition) { - return (condition | ChannelCondition.EXIT_STATUS) == condition; - } - - private boolean hasErrorStream(int condition) { - return (condition | ChannelCondition.STDERR_DATA) == condition; - } - - private ProcessResult executeCommand(Connection sshConnection, String command) { - try { - Session session = sshConnection.openSession(); - BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(new StreamGobbler( - session.getStdout()))); - BufferedReader stderrReader = new BufferedReader(new InputStreamReader(new StreamGobbler( - session.getStderr()))); - session.execCommand(command); - ProcessResult result = getResultOfExecution(session, stdoutReader, stderrReader); - session.close(); - return result; - } catch (IOException e) { - String errMsg = "Exception while executing command [" + command + "] on [" + sshConnection.getHostname() - + "]"; - logger.error(errMsg, e); - throw new GlusterRuntimeException(errMsg, e); - } - } - - private ProcessResult getResultOfExecution(Session session, BufferedReader stdoutReader, BufferedReader stderrReader) { - // Wait for program to come out either - // a) gracefully with an exit status, OR - // b) because of a termination signal - // c) command takes to long to exit (timeout) - int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, - sshExecTimeout); - StringBuilder output = new StringBuilder(); - - try { - if(!timedOut(condition)) { - readFromStream(stdoutReader, output); - if (hasErrors(condition, session)) { - readFromStream(stderrReader, output); - } - } - - return prepareProcessResult(session, condition, output.toString().trim()); - } catch (IOException e) { - String errMsg = "Error while reading output stream from SSH connection!"; - logger.error(errMsg, e); - return new ProcessResult(ProcessResult.FAILURE, errMsg); - } - } - - private ProcessResult prepareProcessResult(Session session, int condition, String output) { - ProcessResult result = null; - - if (wasTerminated(condition)) { - result = new ProcessResult(ProcessResult.FAILURE, output); - } else if (timedOut(condition)) { - result = new ProcessResult(ProcessResult.FAILURE, "Command timed out!"); - } else if (hasErrors(condition, session)) { - Integer exitStatus = session.getExitStatus(); - int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus); - result = new ProcessResult(statusCode, output); - } else { - result = new ProcessResult(ProcessResult.SUCCESS, output); - } - - return result; - } - - private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException { - while (true) { - String line = streamReader.readLine(); - if (line == null) { - break; - } - output.append(line + CoreConstants.NEWLINE); - } - } - - /** - * Executes given command on remote machine using password authentication - * - * @param serverName - * @param command - * @return Result of remote execution - */ - public ProcessResult executeRemoteWithPassword(String serverName, String command) { - return executeCommand(getConnectionWithPassword(serverName), command); - } - - private ProcessResult executeRemoteWithPubKey(String serverName, String command) { - try { - return executeCommand(getConnection(serverName), command); - } catch(GlusterRuntimeException e) { - Throwable cause = e.getCause(); - if(cause != null && cause instanceof IOException) { - // cached ssh connection might have gone bad. - // remove it and try with a new one - sshConnCache.remove(serverName); - return executeCommand(getConnection(serverName), command); - } else { - throw e; - } - } - } - - /** - * Executes given command on remote machine using public key authentication - * - * @param serverName - * @param command - * @return Result of remote execution - */ - public ProcessResult executeRemote(String serverName, String command) { - try { - return executeRemoteWithPubKey(serverName, command); - } catch(ConnectionException e) { - // Couldn't connect with public key. Try with default password. - return executeRemoteWithPassword(serverName, command); - } - } - - /** - * Checks if public key of management gateway is configured on given server - * - * @param serverName - * @return true if public key is configured, else false - */ - public boolean isPublicKeySetup(String serverName) { - try { - getConnection(serverName); - return true; - } catch (Exception e) { - return false; - } - } - - public void cleanup() { - for (Connection conn : sshConnCache.values()) { - conn.close(); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java deleted file mode 100644 index 85487602..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/server/utils/StatsFactory.java +++ /dev/null @@ -1,31 +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.utils; - -import java.util.List; - -import com.gluster.storage.management.core.model.ServerStats; - -/** - * - */ -public interface StatsFactory { - public ServerStats fetchStats(String serverName, String period, String...args); - public ServerStats fetchAggregatedStats(List serverName, String period); -} 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 3cf30ee4..c89eb2f0 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 @@ -7,7 +7,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> - + @@ -69,19 +69,19 @@ - + - com.gluster.storage.management.server.data.ClusterInfo + com.gluster.storage.management.gateway.data.ClusterInfo - + - com.gluster.storage.management.server.data.ServerInfo + com.gluster.storage.management.gateway.data.ServerInfo - - - + \ No newline at end of file -- cgit From ad070fa40d7bcb7c504d5798510874d4a7e6db3a Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Sun, 31 Jul 2011 18:33:21 +0530 Subject: Task #149 - Version based call to python scripts --- .../gateway/resources/v1_0/VolumesResource.java | 17 +++++----- .../gateway/tasks/InitializeDiskTask.java | 22 ++++++------- .../gateway/tasks/RebalanceVolumeTask.java | 15 +++------ .../gateway/utils/AbstractStatsFactory.java | 3 +- .../management/gateway/utils/GlusterUtil.java | 6 ++-- .../management/gateway/utils/ServerUtil.java | 36 +++++++++++++++++++--- 6 files changed, 59 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java index fad19e7e..45df1ae7 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java @@ -84,6 +84,7 @@ 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.exceptions.GlusterValidationException; import com.gluster.storage.management.core.model.Brick; import com.gluster.storage.management.core.model.GlusterServer; import com.gluster.storage.management.core.model.Status; @@ -368,13 +369,13 @@ public class VolumesResource extends AbstractResource { } } - private Status performOperation(String volumeName, String operation, GlusterServer onlineServer) { + private void performOperation(String volumeName, String operation, GlusterServer onlineServer) { if (operation.equals(TASK_START)) { - return glusterUtil.startVolume(volumeName, onlineServer.getName()); + glusterUtil.startVolume(volumeName, onlineServer.getName()); } else if (operation.equals(TASK_STOP)) { - return glusterUtil.stopVolume(volumeName, onlineServer.getName()); + glusterUtil.stopVolume(volumeName, onlineServer.getName()); } else { - return new Status(Status.STATUS_CODE_FAILURE, "Invalid operation code [" + operation + "]"); + throw new GlusterValidationException("Invalid operation code [" + operation + "]"); } } @@ -500,7 +501,7 @@ public class VolumesResource extends AbstractResource { String brickDirectory = brickInfo[1]; String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - Object response = serverUtil.executeOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + Object response = serverUtil.executeScriptOnServer(true, serverName, VOLUME_DIRECTORY_CLEANUP_SCRIPT + " " + mountPoint + " " + volumeName + " " + (deleteFlag ? "-d" : ""), GenericResponse.class); if (response instanceof GenericResponse) { result = ((GenericResponse) response).getStatus(); @@ -524,7 +525,7 @@ public class VolumesResource extends AbstractResource { String brickDirectory = brick.getBrickDirectory(); String mountPoint = brickDirectory.substring(0, brickDirectory.lastIndexOf("/")); - result = (Status) serverUtil.executeOnServer(true, brick.getServerName(), VOLUME_DIRECTORY_CLEANUP_SCRIPT + result = (Status) serverUtil.executeScriptOnServer(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 + "]: " @@ -652,8 +653,8 @@ public class VolumesResource extends AbstractResource { 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); + Object responseObj = serverUtil.executeScriptOnServer(true, brick.getServerName(), VOLUME_BRICK_LOG_SCRIPT + + " " + logFilePath + " " + lineCount, LogMessageListResponse.class); LogMessageListResponse response = null; if (responseObj instanceof LogMessageListResponse) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java index f5cc5332..e7da1de6 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java @@ -33,6 +33,7 @@ import com.gluster.storage.management.core.model.TaskStatus; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.gateway.services.ClusterService; import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; import com.gluster.storage.management.gateway.utils.SshUtil; import com.sun.jersey.core.util.Base64; @@ -43,7 +44,7 @@ public class InitializeDiskTask extends Task { private String serverName; private String diskName; private String fsType; - private SshUtil sshUtil; + private ServerUtil serverUtil; private GlusterUtil glusterUtil; public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, String fsType) { @@ -65,7 +66,7 @@ public class InitializeDiskTask extends Task { private void init() { ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); glusterUtil = ctx.getBean(GlusterUtil.class); - sshUtil = ctx.getBean(SshUtil.class); + serverUtil = ctx.getBean(ServerUtil.class); } @Override @@ -118,17 +119,12 @@ public class InitializeDiskTask extends Task { private void startInitializeDisk(String serverName) { String fsTypeCommand = (getFsType().equals(GlusterConstants.FSTYPE_DEFAULT)) ? "" : " -t " + getFsType(); - ProcessResult processResult = sshUtil.executeRemote(serverName, INITIALIZE_DISK_SCRIPT + fsTypeCommand + " " - + getDiskName()); - if (processResult.isSuccess()) { - TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput())); - taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); - getTaskInfo().setStatus(taskStatus); - return; - } - - // if we reach here, it means Initialize disk start failed. - throw new GlusterRuntimeException(processResult.toString()); + + String output = (String) serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_SCRIPT + + fsTypeCommand + " " + getDiskName(), String.class); + TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output)); + taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); + getTaskInfo().setStatus(taskStatus); } @Override diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java index 3038f961..c53f0252 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java @@ -31,6 +31,7 @@ import com.gluster.storage.management.core.model.TaskStatus; import com.gluster.storage.management.core.utils.ProcessResult; import com.gluster.storage.management.gateway.services.ClusterService; import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; import com.gluster.storage.management.gateway.utils.SshUtil; import com.sun.jersey.core.util.Base64; @@ -38,7 +39,7 @@ public class RebalanceVolumeTask extends Task { private String layout; private String serverName; - private SshUtil sshUtil; + private ServerUtil serverUtil; private GlusterUtil glusterUtil; public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { @@ -51,7 +52,7 @@ public class RebalanceVolumeTask extends Task { private void init() { ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - sshUtil = ctx.getBean(SshUtil.class); + serverUtil = ctx.getBean(ServerUtil.class); glusterUtil = ctx.getBean(GlusterUtil.class); } @@ -74,14 +75,8 @@ public class RebalanceVolumeTask extends Task { private void startRebalance(String serverName) { String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - if (processResult.isSuccess()) { - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput()))); - return; - } - - // if we reach here, it means rebalance start failed. - throw new GlusterRuntimeException(processResult.toString()); + String output = (String)serverUtil.executeOnServer(true, serverName, command, String.class); + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output))); } @Override diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java index 0e73297f..13a58729 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java @@ -155,7 +155,8 @@ public abstract class AbstractStatsFactory implements StatsFactory { argsStr += " " + arg; } } - Object output = serverUtil.executeOnServer(true, serverName, getStatsScriptName() + argsStr + " " + period, ServerStats.class); + Object output = serverUtil.executeScriptOnServer(true, serverName, getStatsScriptName() + argsStr + " " + + period, ServerStats.class); //String cpuUsageData = " 1310468100 300 1310471700 13 3 user system total 13104681002.23802952e-14.3747778209e-016.6128073384e-01 13104684002.3387347338e-014.4642717442e-016.8030064780e-01 13104687005.5043873220e+006.2462376636e+001.1750624986e+01 13104690002.4350593653e+012.6214585217e+015.0565178869e+01 13104693004.0786489953e+014.6784713828e+018.7571203781e+01 13104696004.1459955508e+015.2546309044e+019.4006264551e+01 13104699004.2312286165e+015.2390588332e+019.4702874497e+01 13104702004.2603794982e+015.1598861493e+019.4202656475e+01 13104705003.8238751290e+014.5312089966e+018.3550841256e+01 13104708001.7949961224e+012.1282058418e+013.9232019642e+01 13104711001.2330371421e-014.6347832868e-015.8678204289e-01 13104714001.6313260492e-015.4088119561e-017.0401380052e-01 1310471700NaNNaNNaN "; //Object output = unmarshal(ServerStats.class, cpuUsageData, false); if(output instanceof Status) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java index 7622d283..55909d54 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java @@ -42,7 +42,6 @@ import com.gluster.storage.management.core.model.Server.SERVER_STATUS; import com.gluster.storage.management.core.model.Status; import com.gluster.storage.management.core.model.TaskStatus; import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.model.Volume.NAS_PROTOCOL; import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; @@ -50,7 +49,6 @@ 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.gateway.resources.v1_0.TasksResource; -import com.sun.jersey.api.core.InjectParam; @Component public class GlusterUtil { @@ -617,8 +615,8 @@ public class GlusterUtil { } public TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { - Object response = serverUtil.executeOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + diskName, - InitDiskStatusResponse.class); + Object response = serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + + diskName, InitDiskStatusResponse.class); TaskStatus taskStatus = new TaskStatus(); if (response instanceof Status) { diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java index 0fae0078..91c7c81c 100644 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java +++ b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java @@ -22,6 +22,7 @@ package com.gluster.storage.management.gateway.utils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -54,12 +55,17 @@ public class ServerUtil { @Autowired private SshUtil sshUtil; + @Autowired + private String appVersion; + private static final Logger logger = Logger.getLogger(ServerUtil.class); private static final String SCRIPT_DIR = "scripts"; private static final String SCRIPT_COMMAND = "python"; private static final String REMOTE_SCRIPT_GET_DISK_FOR_DIR = "get_disk_for_dir.py"; private static final String REMOTE_SCRIPT_GET_SERVER_DETAILS = "get_server_details.py"; + private static final String REMOTE_SCRIPT_BASE_DIR = "/opt/glustermg"; + private static final String REMOTE_SCRIPT_DIR_NAME = "backend"; public void setSshUtil(SshUtil sshUtil) { this.sshUtil = sshUtil; @@ -75,8 +81,11 @@ public class ServerUtil { } private String getScriptPath(String scriptName) { - String scriptPath = servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; - return scriptPath; + return servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; + } + + private String getRemoteScriptDir() { + return REMOTE_SCRIPT_BASE_DIR + File.separator + appVersion + File.separator + REMOTE_SCRIPT_DIR_NAME; } /** @@ -98,12 +107,31 @@ public class ServerUtil { private Object fetchServerDetails(String serverName) { // fetch standard server details like cpu, disk, memory details - Object response = executeOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); + Object response = executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); if (response instanceof Status) { throw new GlusterRuntimeException(((Status) response).getMessage()); } return response; } + + /** + * Executes given script on given server. Since the remote server may contain multiple versions of backend, this + * method will invoke the script present in directory of same version as the gateway. + * + * @param runInForeground + * @param serverName + * @param scriptWithArgs + * The script name followed by arguments to be passed. Note that the script name should not contain path + * as it will be automatically identified by the method. + * @param expectedClass + * Class of the object expected from script execution + * @return Object of the expected class from remote execution of the command. In case the remote execution fails + * ungracefully, an object of class {@link Status} will be returned. + */ + public Object executeScriptOnServer(boolean runInForeground, String serverName, String scriptWithArgs, + @SuppressWarnings("rawtypes") Class expectedClass) { + return executeOnServer(runInForeground, serverName, getRemoteScriptDir() + File.separator + scriptWithArgs, expectedClass); + } /** * Executes given command on given server @@ -232,7 +260,7 @@ public class ServerUtil { * @return Status object containing the disk name, or error message in case the remote script fails. */ public Status getDiskForDir(String serverName, String brickDir) { - return (Status) executeOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); + return (Status) executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); } public static void main(String[] args) { -- cgit From 1d60963ce1b6fb2f49317ce9174a7764f3eafc00 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Sun, 31 Jul 2011 18:36:50 +0530 Subject: Renamed project and package com.gluster.storage.management.server to com.gluster.storage.management.gateway --- .../com.gluster.storage.management.gateway.cquery | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery index 346b39bf..1f663cbe 100644 --- a/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery +++ b/src/com.gluster.storage.management.releng/com.gluster.storage.management.gateway.cquery @@ -1,4 +1,4 @@ - + -- cgit From 0d12b25f91cfcbb09687d774389d85b8c8ffa249 Mon Sep 17 00:00:00 2001 From: Shireesh Anjal Date: Mon, 1 Aug 2011 11:54:01 +0530 Subject: Renamed project and package com.gluster.storage.management.server to com.gluster.storage.management.gateway --- .../.project | 17 + .../.pydevproject | 10 + .../src/Commands.py | 78 ++ .../src/Common.py | 20 + .../src/Disk.py | 140 +++ .../src/DiskUtils.py | 948 ++++++++++++++++++ .../src/FsTabUtils.py | 92 ++ .../src/GetServerNetworkConfig.py | 96 ++ .../src/Globals.py | 123 +++ .../src/GlusterdUtils.py | 250 +++++ .../src/NetworkUtils.py | 483 +++++++++ .../src/Protocol.py | 438 ++++++++ .../src/RRDUtils.py | 72 ++ .../src/ServerUtils.py | 308 ++++++ .../src/Utils.py | 1059 ++++++++++++++++++++ .../src/VolumeUtils.py | 612 +++++++++++ .../src/XmlHandler.py | 346 +++++++ .../src/add_user_cifs.py | 37 + .../src/clear_volume_directory.py | 97 ++ .../src/create_volume_cifs.py | 33 + .../src/create_volume_directory.py | 82 ++ .../src/delete_user_cifs.py | 24 + .../src/delete_volume_cifs.py | 32 + .../src/disable-ssh-password-auth.sh | 30 + .../src/format_device.py | 87 ++ .../src/get_brick_status.py | 40 + .../src/get_disk_mount_point.py | 62 ++ .../src/get_disk_name_by_path.py | 68 ++ .../src/get_file.py | 130 +++ .../src/get_format_device_status.py | 124 +++ .../src/get_rrd_cpu_details.py | 55 + .../src/get_rrd_memory_details.py | 89 ++ .../src/get_rrd_net_details.py | 52 + .../src/get_server_details.py | 118 +++ .../src/get_server_status.py | 22 + .../src/get_volume_brick_log.py | 103 ++ .../src/get_volume_log.py | 131 +++ .../src/gluster_provision_block_wrapper.py | 109 ++ .../src/modify_volume_cifs.py | 28 + .../src/multicast_response.py | 74 ++ .../src/rrd_cpu.pl | 84 ++ .../src/rrd_mem.pl | 100 ++ .../src/rrd_net.pl | 74 ++ .../src/rrd_update_cpu_details.py | 90 ++ .../src/rrd_update_memory_details.py | 90 ++ .../src/setup_cifs_config.py | 81 ++ .../src/start_volume_cifs.py | 41 + .../src/stop_volume_cifs.py | 38 + .../.classpath | 15 + .../.project | 41 + .../.settings/.jsdtscope | 12 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../org.eclipse.ltk.core.refactoring.prefs | 3 + .../.settings/org.eclipse.wst.common.component | 10 + .../org.eclipse.wst.common.project.facet.core.xml | 20 + .../org.eclipse.wst.jsdt.ui.superType.container | 1 + .../org.eclipse.wst.jsdt.ui.superType.name | 1 + .../org.eclipse.wst.ws.service.policy.prefs | 3 + .../WebContent/META-INF/MANIFEST.MF | 3 + .../WebContent/WEB-INF/lib/antlr-2.7.6.jar | Bin 0 -> 443432 bytes .../WebContent/WEB-INF/lib/aopalliance-1.0.jar | Bin 0 -> 4467 bytes .../WebContent/WEB-INF/lib/asm-3.1.jar | Bin 0 -> 43033 bytes .../WEB-INF/lib/commons-collections-3.1.jar | Bin 0 -> 559366 bytes .../WEB-INF/lib/commons-logging-1.1.1.jar | Bin 0 -> 60841 bytes .../WebContent/WEB-INF/lib/derby.jar | Bin 0 -> 2512189 bytes .../WebContent/WEB-INF/lib/derbytools.jar | Bin 0 -> 165188 bytes .../WebContent/WEB-INF/lib/dom4j-1.6.1.jar | Bin 0 -> 313898 bytes .../WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt | 87 ++ .../WEB-INF/lib/ganymed-ssh2-build250.jar | Bin 0 -> 248915 bytes .../lib/hibernate-jpa-2.0-api-1.0.0.Final.jar | Bin 0 -> 100884 bytes .../WebContent/WEB-INF/lib/hibernate3.jar | Bin 0 -> 4133342 bytes .../WEB-INF/lib/jackson-core-asl-1.5.5.jar | Bin 0 -> 171958 bytes .../WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar | Bin 0 -> 17065 bytes .../WEB-INF/lib/jackson-mapper-asl-1.5.5.jar | Bin 0 -> 485699 bytes .../WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar | Bin 0 -> 24745 bytes .../WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar | Bin 0 -> 633312 bytes .../WebContent/WEB-INF/lib/jersey-client-1.5.jar | Bin 0 -> 128096 bytes .../WebContent/WEB-INF/lib/jersey-core-1.5.jar | Bin 0 -> 455665 bytes .../WebContent/WEB-INF/lib/jersey-json-1.5.jar | Bin 0 -> 144810 bytes .../WEB-INF/lib/jersey-multipart-1.5.jar | Bin 0 -> 49330 bytes .../WebContent/WEB-INF/lib/jersey-server-1.5.jar | Bin 0 -> 681117 bytes .../WebContent/WEB-INF/lib/jersey-spring-1.5.jar | Bin 0 -> 17079 bytes .../WebContent/WEB-INF/lib/jettison-1.1.jar | Bin 0 -> 67758 bytes .../WebContent/WEB-INF/lib/jnlp-servlet.jar | Bin 0 -> 61712 bytes .../WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar | Bin 0 -> 46367 bytes .../WebContent/WEB-INF/lib/jta-1.1.jar | Bin 0 -> 10899 bytes .../WebContent/WEB-INF/lib/log4j-1.2.16.jar | Bin 0 -> 481534 bytes .../WebContent/WEB-INF/lib/mimepull-1.3.jar | Bin 0 -> 38683 bytes .../org.eclipse.equinox.common_3.6.0.v20100503.jar | Bin 0 -> 101958 bytes .../lib/org.springframework.aop-3.0.5.RELEASE.jar | Bin 0 -> 321190 bytes .../lib/org.springframework.asm-3.0.5.RELEASE.jar | Bin 0 -> 53082 bytes .../org.springframework.aspects-3.0.5.RELEASE.jar | Bin 0 -> 35548 bytes .../org.springframework.beans-3.0.5.RELEASE.jar | Bin 0 -> 555410 bytes .../org.springframework.context-3.0.5.RELEASE.jar | Bin 0 -> 668861 bytes ...ringframework.context.support-3.0.5.RELEASE.jar | Bin 0 -> 100870 bytes .../lib/org.springframework.core-3.0.5.RELEASE.jar | Bin 0 -> 382442 bytes ...rg.springframework.expression-3.0.5.RELEASE.jar | Bin 0 -> 169752 bytes ...rg.springframework.instrument-3.0.5.RELEASE.jar | Bin 0 -> 1810 bytes ...ngframework.instrument.tomcat-3.0.5.RELEASE.jar | Bin 0 -> 5728 bytes .../lib/org.springframework.jdbc-3.0.5.RELEASE.jar | Bin 0 -> 385712 bytes .../lib/org.springframework.jms-3.0.5.RELEASE.jar | Bin 0 -> 185312 bytes .../lib/org.springframework.orm-3.0.5.RELEASE.jar | Bin 0 -> 334327 bytes .../lib/org.springframework.oxm-3.0.5.RELEASE.jar | Bin 0 -> 61379 bytes ...ringframework.spring-library-3.0.5.RELEASE.libd | 21 + .../lib/org.springframework.test-3.0.5.RELEASE.jar | Bin 0 -> 205278 bytes ...g.springframework.transaction-3.0.5.RELEASE.jar | Bin 0 -> 231922 bytes .../lib/org.springframework.web-3.0.5.RELEASE.jar | Bin 0 -> 395587 bytes ...g.springframework.web.portlet-3.0.5.RELEASE.jar | Bin 0 -> 175412 bytes ...g.springframework.web.servlet-3.0.5.RELEASE.jar | Bin 0 -> 418977 bytes ...rg.springframework.web.struts-3.0.5.RELEASE.jar | Bin 0 -> 31404 bytes ...com.gluster.storage.management.client_1.0.0.jar | Bin 0 -> 513103 bytes .../com.gluster.storage.management.core_1.0.0.jar | Bin 0 -> 50608 bytes .../WebContent/WEB-INF/lib/servlet-api.jar | Bin 0 -> 176386 bytes .../WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar | Bin 0 -> 25496 bytes .../lib/spring-security-config-3.0.5.RELEASE.jar | Bin 0 -> 185716 bytes .../lib/spring-security-core-3.0.5.RELEASE.jar | Bin 0 -> 311038 bytes .../lib/spring-security-web-3.0.5.RELEASE.jar | Bin 0 -> 242833 bytes .../WebContent/WEB-INF/web.xml | 73 ++ .../WebContent/data/scripts/1.0.0/0-version.sql | 2 + .../data/scripts/1.0.0/1-security-schema.sql | 26 + .../scripts/1.0.0/2-users-authorities-groups.sql | 21 + .../data/scripts/1.0.0/3-cluster-servers.sql | 16 + .../WebContent/index.html | 8 + .../WebContent/scripts/Globals.py | 123 +++ .../WebContent/scripts/Protocol.py | 438 ++++++++ .../WebContent/scripts/Utils.py | 1059 ++++++++++++++++++++ .../WebContent/scripts/XmlHandler.py | 346 +++++++ .../WebContent/scripts/add_user_cifs_all.py | 66 ++ .../WebContent/scripts/delete_user_cifs_all.py | 53 + .../WebContent/scripts/grun.py | 36 + .../scripts/multicast-discover-servers.py | 90 ++ .../WebContent/ssl/gmg-ssl.keystore | Bin 0 -> 1380 bytes .../buckminster.cspex | 37 + .../build/glusterserver.ant | 65 ++ .../src/META-INF/persistence.xml | 5 + .../gateway/constants/VolumeOptionsDefaults.java | 118 +++ .../management/gateway/data/ClusterInfo.java | 79 ++ .../management/gateway/data/GlusterDataSource.java | 48 + .../management/gateway/data/PersistenceDao.java | 113 +++ .../management/gateway/data/ServerInfo.java | 72 ++ .../management/gateway/filters/AuditFilter.java | 38 + .../filters/AuthenticationFailureFilter.java | 105 ++ .../filters/GlusterResourceFilterFactory.java | 31 + .../gateway/resources/v1_0/AbstractResource.java | 177 ++++ .../gateway/resources/v1_0/ClustersResource.java | 126 +++ .../resources/v1_0/DiscoveredServersResource.java | 150 +++ .../resources/v1_0/GenericExceptionMapper.java | 54 + .../resources/v1_0/GlusterServersResource.java | 487 +++++++++ .../gateway/resources/v1_0/KeysResource.java | 153 +++ .../gateway/resources/v1_0/TasksResource.java | 194 ++++ .../gateway/resources/v1_0/UsersResource.java | 91 ++ .../gateway/resources/v1_0/VolumesResource.java | 989 ++++++++++++++++++ .../security/GlusterUserDetailsService.java | 31 + .../management/gateway/security/UserAuthDao.java | 42 + .../gateway/services/ClusterService.java | 269 +++++ .../gateway/services/GlusterServerService.java | 165 +++ .../management/gateway/tasks/InitServerTask.java | 162 +++ .../gateway/tasks/InitializeDiskTask.java | 164 +++ .../management/gateway/tasks/MigrateBrickTask.java | 227 +++++ .../gateway/tasks/RebalanceVolumeTask.java | 129 +++ .../management/gateway/tasks/ServerSyncTask.java | 154 +++ .../storage/management/gateway/tasks/Task.java | 112 +++ .../gateway/utils/AbstractStatsFactory.java | 169 ++++ .../management/gateway/utils/CpuStatsFactory.java | 36 + .../management/gateway/utils/GlusterUtil.java | 662 ++++++++++++ .../gateway/utils/MemoryStatsFactory.java | 68 ++ .../gateway/utils/NetworkStatsFactory.java | 123 +++ .../management/gateway/utils/ServerUtil.java | 286 ++++++ .../storage/management/gateway/utils/SshUtil.java | 388 +++++++ .../management/gateway/utils/StatsFactory.java | 31 + .../src/log4j.properties | 19 + .../src/spring/gluster-server-base.xml | 100 ++ .../src/spring/gluster-server-security.xml | 43 + .../.project | 17 - .../.pydevproject | 10 - .../src/Commands.py | 78 -- .../src/Common.py | 20 - .../src/Disk.py | 140 --- .../src/DiskUtils.py | 948 ------------------ .../src/FsTabUtils.py | 92 -- .../src/GetServerNetworkConfig.py | 96 -- .../src/Globals.py | 123 --- .../src/GlusterdUtils.py | 250 ----- .../src/NetworkUtils.py | 483 --------- .../src/Protocol.py | 438 -------- .../src/RRDUtils.py | 72 -- .../src/ServerUtils.py | 308 ------ .../src/Utils.py | 1059 -------------------- .../src/VolumeUtils.py | 612 ----------- .../src/XmlHandler.py | 346 ------- .../src/add_user_cifs.py | 37 - .../src/clear_volume_directory.py | 97 -- .../src/create_volume_cifs.py | 33 - .../src/create_volume_directory.py | 82 -- .../src/delete_user_cifs.py | 24 - .../src/delete_volume_cifs.py | 32 - .../src/disable-ssh-password-auth.sh | 30 - .../src/format_device.py | 87 -- .../src/get_brick_status.py | 40 - .../src/get_disk_mount_point.py | 62 -- .../src/get_disk_name_by_path.py | 68 -- .../src/get_file.py | 130 --- .../src/get_format_device_status.py | 124 --- .../src/get_rrd_cpu_details.py | 55 - .../src/get_rrd_memory_details.py | 89 -- .../src/get_rrd_net_details.py | 52 - .../src/get_server_details.py | 118 --- .../src/get_server_status.py | 22 - .../src/get_volume_brick_log.py | 103 -- .../src/get_volume_log.py | 131 --- .../src/gluster_provision_block_wrapper.py | 109 -- .../src/modify_volume_cifs.py | 28 - .../src/multicast_response.py | 74 -- .../src/rrd_cpu.pl | 84 -- .../src/rrd_mem.pl | 100 -- .../src/rrd_net.pl | 74 -- .../src/rrd_update_cpu_details.py | 90 -- .../src/rrd_update_memory_details.py | 90 -- .../src/setup_cifs_config.py | 81 -- .../src/start_volume_cifs.py | 41 - .../src/stop_volume_cifs.py | 38 - .../.classpath | 15 - src/com.gluster.storage.management.server/.project | 41 - .../.settings/.jsdtscope | 12 - .../.settings/org.eclipse.jdt.core.prefs | 8 - .../org.eclipse.ltk.core.refactoring.prefs | 3 - .../.settings/org.eclipse.wst.common.component | 10 - .../org.eclipse.wst.common.project.facet.core.xml | 20 - .../org.eclipse.wst.jsdt.ui.superType.container | 1 - .../org.eclipse.wst.jsdt.ui.superType.name | 1 - .../org.eclipse.wst.ws.service.policy.prefs | 3 - .../WebContent/META-INF/MANIFEST.MF | 3 - .../WebContent/WEB-INF/lib/antlr-2.7.6.jar | Bin 443432 -> 0 bytes .../WebContent/WEB-INF/lib/aopalliance-1.0.jar | Bin 4467 -> 0 bytes .../WebContent/WEB-INF/lib/asm-3.1.jar | Bin 43033 -> 0 bytes .../WEB-INF/lib/commons-collections-3.1.jar | Bin 559366 -> 0 bytes .../WEB-INF/lib/commons-logging-1.1.1.jar | Bin 60841 -> 0 bytes .../WebContent/WEB-INF/lib/derby.jar | Bin 2512189 -> 0 bytes .../WebContent/WEB-INF/lib/derbytools.jar | Bin 165188 -> 0 bytes .../WebContent/WEB-INF/lib/dom4j-1.6.1.jar | Bin 313898 -> 0 bytes .../WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt | 87 -- .../WEB-INF/lib/ganymed-ssh2-build250.jar | Bin 248915 -> 0 bytes .../lib/hibernate-jpa-2.0-api-1.0.0.Final.jar | Bin 100884 -> 0 bytes .../WebContent/WEB-INF/lib/hibernate3.jar | Bin 4133342 -> 0 bytes .../WEB-INF/lib/jackson-core-asl-1.5.5.jar | Bin 171958 -> 0 bytes .../WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar | Bin 17065 -> 0 bytes .../WEB-INF/lib/jackson-mapper-asl-1.5.5.jar | Bin 485699 -> 0 bytes .../WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar | Bin 24745 -> 0 bytes .../WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar | Bin 633312 -> 0 bytes .../WebContent/WEB-INF/lib/jersey-client-1.5.jar | Bin 128096 -> 0 bytes .../WebContent/WEB-INF/lib/jersey-core-1.5.jar | Bin 455665 -> 0 bytes .../WebContent/WEB-INF/lib/jersey-json-1.5.jar | Bin 144810 -> 0 bytes .../WEB-INF/lib/jersey-multipart-1.5.jar | Bin 49330 -> 0 bytes .../WebContent/WEB-INF/lib/jersey-server-1.5.jar | Bin 681117 -> 0 bytes .../WebContent/WEB-INF/lib/jersey-spring-1.5.jar | Bin 17079 -> 0 bytes .../WebContent/WEB-INF/lib/jettison-1.1.jar | Bin 67758 -> 0 bytes .../WebContent/WEB-INF/lib/jnlp-servlet.jar | Bin 61712 -> 0 bytes .../WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar | Bin 46367 -> 0 bytes .../WebContent/WEB-INF/lib/jta-1.1.jar | Bin 10899 -> 0 bytes .../WebContent/WEB-INF/lib/log4j-1.2.16.jar | Bin 481534 -> 0 bytes .../WebContent/WEB-INF/lib/mimepull-1.3.jar | Bin 38683 -> 0 bytes .../org.eclipse.equinox.common_3.6.0.v20100503.jar | Bin 101958 -> 0 bytes .../lib/org.springframework.aop-3.0.5.RELEASE.jar | Bin 321190 -> 0 bytes .../lib/org.springframework.asm-3.0.5.RELEASE.jar | Bin 53082 -> 0 bytes .../org.springframework.aspects-3.0.5.RELEASE.jar | Bin 35548 -> 0 bytes .../org.springframework.beans-3.0.5.RELEASE.jar | Bin 555410 -> 0 bytes .../org.springframework.context-3.0.5.RELEASE.jar | Bin 668861 -> 0 bytes ...ringframework.context.support-3.0.5.RELEASE.jar | Bin 100870 -> 0 bytes .../lib/org.springframework.core-3.0.5.RELEASE.jar | Bin 382442 -> 0 bytes ...rg.springframework.expression-3.0.5.RELEASE.jar | Bin 169752 -> 0 bytes ...rg.springframework.instrument-3.0.5.RELEASE.jar | Bin 1810 -> 0 bytes ...ngframework.instrument.tomcat-3.0.5.RELEASE.jar | Bin 5728 -> 0 bytes .../lib/org.springframework.jdbc-3.0.5.RELEASE.jar | Bin 385712 -> 0 bytes .../lib/org.springframework.jms-3.0.5.RELEASE.jar | Bin 185312 -> 0 bytes .../lib/org.springframework.orm-3.0.5.RELEASE.jar | Bin 334327 -> 0 bytes .../lib/org.springframework.oxm-3.0.5.RELEASE.jar | Bin 61379 -> 0 bytes ...ringframework.spring-library-3.0.5.RELEASE.libd | 21 - .../lib/org.springframework.test-3.0.5.RELEASE.jar | Bin 205278 -> 0 bytes ...g.springframework.transaction-3.0.5.RELEASE.jar | Bin 231922 -> 0 bytes .../lib/org.springframework.web-3.0.5.RELEASE.jar | Bin 395587 -> 0 bytes ...g.springframework.web.portlet-3.0.5.RELEASE.jar | Bin 175412 -> 0 bytes ...g.springframework.web.servlet-3.0.5.RELEASE.jar | Bin 418977 -> 0 bytes ...rg.springframework.web.struts-3.0.5.RELEASE.jar | Bin 31404 -> 0 bytes ...com.gluster.storage.management.client_1.0.0.jar | Bin 513103 -> 0 bytes .../com.gluster.storage.management.core_1.0.0.jar | Bin 50608 -> 0 bytes .../WebContent/WEB-INF/lib/servlet-api.jar | Bin 176386 -> 0 bytes .../WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar | Bin 25496 -> 0 bytes .../lib/spring-security-config-3.0.5.RELEASE.jar | Bin 185716 -> 0 bytes .../lib/spring-security-core-3.0.5.RELEASE.jar | Bin 311038 -> 0 bytes .../lib/spring-security-web-3.0.5.RELEASE.jar | Bin 242833 -> 0 bytes .../WebContent/WEB-INF/web.xml | 73 -- .../WebContent/data/scripts/1.0.0/0-version.sql | 2 - .../data/scripts/1.0.0/1-security-schema.sql | 26 - .../scripts/1.0.0/2-users-authorities-groups.sql | 21 - .../data/scripts/1.0.0/3-cluster-servers.sql | 16 - .../WebContent/index.html | 8 - .../WebContent/scripts/Globals.py | 123 --- .../WebContent/scripts/Protocol.py | 438 -------- .../WebContent/scripts/Utils.py | 1059 -------------------- .../WebContent/scripts/XmlHandler.py | 346 ------- .../WebContent/scripts/add_user_cifs_all.py | 66 -- .../WebContent/scripts/delete_user_cifs_all.py | 53 - .../WebContent/scripts/grun.py | 36 - .../scripts/multicast-discover-servers.py | 90 -- .../WebContent/ssl/gmg-ssl.keystore | Bin 1380 -> 0 bytes .../buckminster.cspex | 37 - .../build/glusterserver.ant | 65 -- .../src/META-INF/persistence.xml | 5 - .../gateway/constants/VolumeOptionsDefaults.java | 118 --- .../management/gateway/data/ClusterInfo.java | 79 -- .../management/gateway/data/GlusterDataSource.java | 48 - .../management/gateway/data/PersistenceDao.java | 113 --- .../management/gateway/data/ServerInfo.java | 72 -- .../management/gateway/filters/AuditFilter.java | 38 - .../filters/AuthenticationFailureFilter.java | 105 -- .../filters/GlusterResourceFilterFactory.java | 31 - .../gateway/resources/v1_0/AbstractResource.java | 177 ---- .../gateway/resources/v1_0/ClustersResource.java | 126 --- .../resources/v1_0/DiscoveredServersResource.java | 150 --- .../resources/v1_0/GenericExceptionMapper.java | 54 - .../resources/v1_0/GlusterServersResource.java | 487 --------- .../gateway/resources/v1_0/KeysResource.java | 153 --- .../gateway/resources/v1_0/TasksResource.java | 194 ---- .../gateway/resources/v1_0/UsersResource.java | 91 -- .../gateway/resources/v1_0/VolumesResource.java | 989 ------------------ .../security/GlusterUserDetailsService.java | 31 - .../management/gateway/security/UserAuthDao.java | 42 - .../gateway/services/ClusterService.java | 269 ----- .../gateway/services/GlusterServerService.java | 165 --- .../management/gateway/tasks/InitServerTask.java | 162 --- .../gateway/tasks/InitializeDiskTask.java | 164 --- .../management/gateway/tasks/MigrateBrickTask.java | 227 ----- .../gateway/tasks/RebalanceVolumeTask.java | 129 --- .../management/gateway/tasks/ServerSyncTask.java | 154 --- .../storage/management/gateway/tasks/Task.java | 112 --- .../gateway/utils/AbstractStatsFactory.java | 169 ---- .../management/gateway/utils/CpuStatsFactory.java | 36 - .../management/gateway/utils/GlusterUtil.java | 662 ------------ .../gateway/utils/MemoryStatsFactory.java | 68 -- .../gateway/utils/NetworkStatsFactory.java | 123 --- .../management/gateway/utils/ServerUtil.java | 286 ------ .../storage/management/gateway/utils/SshUtil.java | 388 ------- .../management/gateway/utils/StatsFactory.java | 31 - .../src/log4j.properties | 19 - .../src/spring/gluster-server-base.xml | 100 -- .../src/spring/gluster-server-security.xml | 43 - 346 files changed, 16411 insertions(+), 16411 deletions(-) create mode 100644 src/com.gluster.storage.management.gateway.scripts/.project create mode 100644 src/com.gluster.storage.management.gateway.scripts/.pydevproject create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/Commands.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/Common.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/Disk.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/Globals.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/Protocol.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/Utils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/format_device.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_file.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py create mode 100644 src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py create mode 100755 src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py create mode 100644 src/com.gluster.storage.management.gateway/.classpath create mode 100644 src/com.gluster.storage.management.gateway/.project create mode 100644 src/com.gluster.storage.management.gateway/.settings/.jsdtscope create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.ltk.core.refactoring.prefs create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.component create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.container create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.name create mode 100644 src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.ws.service.policy.prefs create mode 100644 src/com.gluster.storage.management.gateway/WebContent/META-INF/MANIFEST.MF create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/antlr-2.7.6.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/aopalliance-1.0.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/asm-3.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-collections-3.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derby.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derbytools.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/dom4j-1.6.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate3.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-client-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-core-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-json-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-server-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-spring-1.5.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jettison-1.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jnlp-servlet.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jta-1.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/log4j-1.2.16.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/mimepull-1.3.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/servlet-api.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar create mode 100644 src/com.gluster.storage.management.gateway/WebContent/WEB-INF/web.xml create mode 100644 src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/0-version.sql create mode 100644 src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/1-security-schema.sql create mode 100644 src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql create mode 100644 src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/3-cluster-servers.sql create mode 100644 src/com.gluster.storage.management.gateway/WebContent/index.html create mode 100644 src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py create mode 100644 src/com.gluster.storage.management.gateway/WebContent/scripts/Protocol.py create mode 100644 src/com.gluster.storage.management.gateway/WebContent/scripts/Utils.py create mode 100644 src/com.gluster.storage.management.gateway/WebContent/scripts/XmlHandler.py create mode 100755 src/com.gluster.storage.management.gateway/WebContent/scripts/add_user_cifs_all.py create mode 100755 src/com.gluster.storage.management.gateway/WebContent/scripts/delete_user_cifs_all.py create mode 100755 src/com.gluster.storage.management.gateway/WebContent/scripts/grun.py create mode 100755 src/com.gluster.storage.management.gateway/WebContent/scripts/multicast-discover-servers.py create mode 100644 src/com.gluster.storage.management.gateway/WebContent/ssl/gmg-ssl.keystore create mode 100644 src/com.gluster.storage.management.gateway/buckminster.cspex create mode 100644 src/com.gluster.storage.management.gateway/build/glusterserver.ant create mode 100644 src/com.gluster.storage.management.gateway/src/META-INF/persistence.xml create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ClusterInfo.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/PersistenceDao.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ServerInfo.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuditFilter.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/UserAuthDao.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/ClusterService.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/GlusterServerService.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/Task.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java create mode 100644 src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/StatsFactory.java create mode 100644 src/com.gluster.storage.management.gateway/src/log4j.properties create mode 100644 src/com.gluster.storage.management.gateway/src/spring/gluster-server-base.xml create mode 100644 src/com.gluster.storage.management.gateway/src/spring/gluster-server-security.xml delete mode 100644 src/com.gluster.storage.management.server.scripts/.project delete mode 100644 src/com.gluster.storage.management.server.scripts/.pydevproject delete mode 100644 src/com.gluster.storage.management.server.scripts/src/Commands.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/Common.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/Disk.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/DiskUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/FsTabUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/GetServerNetworkConfig.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/Globals.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/GlusterdUtils.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/NetworkUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/Protocol.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/RRDUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/ServerUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/Utils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/VolumeUtils.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/XmlHandler.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/add_user_cifs.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/clear_volume_directory.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/create_volume_cifs.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/create_volume_directory.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/delete_user_cifs.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/delete_volume_cifs.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/disable-ssh-password-auth.sh delete mode 100755 src/com.gluster.storage.management.server.scripts/src/format_device.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_brick_status.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_disk_mount_point.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_disk_name_by_path.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_file.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_format_device_status.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_rrd_cpu_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_rrd_memory_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_rrd_net_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_server_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_server_status.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_volume_brick_log.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/get_volume_log.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/gluster_provision_block_wrapper.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/modify_volume_cifs.py delete mode 100644 src/com.gluster.storage.management.server.scripts/src/multicast_response.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/rrd_cpu.pl delete mode 100755 src/com.gluster.storage.management.server.scripts/src/rrd_mem.pl delete mode 100755 src/com.gluster.storage.management.server.scripts/src/rrd_net.pl delete mode 100755 src/com.gluster.storage.management.server.scripts/src/rrd_update_cpu_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/rrd_update_memory_details.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/setup_cifs_config.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/start_volume_cifs.py delete mode 100755 src/com.gluster.storage.management.server.scripts/src/stop_volume_cifs.py delete mode 100644 src/com.gluster.storage.management.server/.classpath delete mode 100644 src/com.gluster.storage.management.server/.project delete mode 100644 src/com.gluster.storage.management.server/.settings/.jsdtscope delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name delete mode 100644 src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs delete mode 100644 src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/antlr-2.7.6.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-collections-3.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/dom4j-1.6.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate3.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jta-1.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/log4j-1.2.16.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/mimepull-1.3.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar delete mode 100644 src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml delete mode 100644 src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/0-version.sql delete mode 100644 src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/1-security-schema.sql delete mode 100644 src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql delete mode 100644 src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/3-cluster-servers.sql delete mode 100644 src/com.gluster.storage.management.server/WebContent/index.html delete mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/Globals.py delete mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py delete mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/Utils.py delete mode 100644 src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py delete mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/add_user_cifs_all.py delete mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/delete_user_cifs_all.py delete mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/grun.py delete mode 100755 src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py delete mode 100644 src/com.gluster.storage.management.server/WebContent/ssl/gmg-ssl.keystore delete mode 100644 src/com.gluster.storage.management.server/buckminster.cspex delete mode 100644 src/com.gluster.storage.management.server/build/glusterserver.ant delete mode 100644 src/com.gluster.storage.management.server/src/META-INF/persistence.xml delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java delete mode 100644 src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java delete mode 100644 src/com.gluster.storage.management.server/src/log4j.properties delete mode 100644 src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml delete mode 100644 src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml (limited to 'src') diff --git a/src/com.gluster.storage.management.gateway.scripts/.project b/src/com.gluster.storage.management.gateway.scripts/.project new file mode 100644 index 00000000..110db62b --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/.project @@ -0,0 +1,17 @@ + + + com.gluster.storage.management.gateway.scripts + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/src/com.gluster.storage.management.gateway.scripts/.pydevproject b/src/com.gluster.storage.management.gateway.scripts/.pydevproject new file mode 100644 index 00000000..c327cd69 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/.pydevproject @@ -0,0 +1,10 @@ + + + + +Default +python 3.0 + +/com.gluster.storage.management.gateway.scripts/src + + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Commands.py b/src/com.gluster.storage.management.gateway.scripts/src/Commands.py new file mode 100644 index 00000000..c728b565 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Commands.py @@ -0,0 +1,78 @@ +COMMAND_CREATE_VOLUME = "create-volume" +COMMAND_DELETE_VOLUME = "delete-volume" +COMMAND_START_VOLUME = "start-volume" +COMMAND_STOP_VOLUME = "stop-volume" +COMMAND_GET_VOLUME_HEALTH_STATUS = "get-volume-health-status" +COMMAND_GET_VOLUME_LIST = "get-volume-list" +COMMAND_GET_VOLUME_LOG = "get-volume-log" +COMMAND_CLEAR_VOLUME_LOGS = "clear-volume-logs" +COMMAND_GET_VOLUME_PROPERTY = "get-volume-property" +COMMAND_SET_VOLUME_PROPERTY = "set-volume-property" +COMMAND_GET_VOLUME_STATUS = "get-volume-status" +COMMAND_DOWNLOAD_VOLUME_LOGS = "download-volume-logs" +COMMAND_DELETE_SERVER = "delete-server" +COMMAND_GET_SERVER_DATE = "get-server-date" +COMMAND_GET_SERVER_VERSION_INFO = "get-server-version-info" +COMMAND_GET_INSTALLER_INFO = "get-installer-info" +COMMAND_GET_SERVER_LIST = "get-server-list" +COMMAND_GET_SERVER_SERVICE_STATUS = "get-server-service-status" +COMMAND_GET_STORAGE_SERVER_POOL_INFO = "get-storage-server-pool-info" +COMMAND_INSTALL_SERVER_BACKGROUND = "install-server-background" +COMMAND_PREPARE_DATA_DISK_BACKGROUND = "prepare-data-disk-background" +COMMAND_SET_SERVER_DATE = "set-server-date" +COMMAND_SET_SERVER_NETWORK_CONFIG = "set-server-network-config" +COMMAND_SET_STORAGE_SERVER_POOL_INFO = "set-storage-server-pool-info" +COMMAND_GET_SERVER_NETWORK_CONFIG = "get-server-network-config" +COMMAND_INSTALL_SERVER_STATUS = "install-server-status" +COMMAND_GET_SERVER_DISK_LIST = "get-server-disk-list" +COMMAND_PREPARE_DATA_DISK_STATUS = "prepare-data-disk-status" +COMMAND_GET_SERVER_SYSTEM_RESOURCE = "get-server-system-resource" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SHUTDOWN_SERVER = "shutdown-server" +COMMAND_GET_SERVER_STATUS = "get-server-status" +COMMAND_GET_SERVER_LOG = "get-server-log" +COMMAND_DOWNLOAD_SERVER_LOGS = "download-server-logs" +COMMAND_CLEAR_SERVER_LOGS = "clear-server-logs" +COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" +COMMAND_GET_GSN_USER_INFO = "get-gsn-user-info" +COMMAND_SET_GSN_USER_INFO = "set-gsn-user-info" +COMMAND_GET_GLUSTER_UPDATE_INFO = "get-gluster-update-info" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_BACKGROUND = "download-gluster-update-background" +COMMAND_DOWNLOAD_GLUSTER_UPDATE_STATUS = "download-gluster-update-status" +COMMAND_INSTALL_GLUSTER_UPDATE = "install-gluster-update" +COMMAND_EXPORT_CONFIG = "export-config" +COMMAND_IMPORT_CONFIG = "import-config" +COMMAND_SET_SYSTEM_PASSWORD = "set-system-password" +COMMAND_GET_SERVER_VOLUME_LIST = "get-server-volume-list" +COMMAND_RECONFIGURE_VOLUME = "reconfigure-volume" +COMMAND_SET_SERVER_DIRECTORY_SERVICE_CONFIG = "set-server-directory-service-config" +COMMAND_GET_SERVER_DIRECTORY_SERVICE_CONFIG = "get-server-directory-service-config" +COMMAND_JOIN_SERVER_TO_DIRECTORY_SERVICE = "join-server-to-directory-service" +COMMAND_SET_SERVER_TIME_CONFIG = "set-server-time-config" +COMMAND_GET_SERVER_TIME_CONFIG = "get-server-time-config" +COMMAND_LOGIN = "login" +COMMAND_LOGOUT = "logout" +COMMAND_GET_LOGIN_STATUS = "get-login-status" +COMMAND_GET_SERVER_TRANSPORT_LIST = "get-server-transport-list" +COMMAND_ADD_SERVER_PARTITION = "add-server-partition" +COMMAND_ADD_VOLUME_USER = "add-volume-user" +COMMAND_GET_PARTITION_VOLUME_LIST = "get-partition-volume-list" +COMMAND_GET_VOLUME_USER_INFO = "get-volume-user-info" +COMMAND_GET_VOLUME_USER_LIST = "get-volume-user-list" +COMMAND_MIGRATE_PARTITION_BACKGROUND = "migrate-partition-background" +COMMAND_MIGRATE_PARTITION_STATUS = "migrate-partition-status" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_BACKGROUND = "migrate-volume-server-partition-background" +COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_STATUS = "migrate-volume-server-partition-status" +COMMAND_REMOVE_SERVER_PARTITION = "remove-server-partition" +COMMAND_REMOVE_VOLUME_USER = "remove-volume-user" +COMMAND_RENAME_VOLUME_USER = "rename-volume-user" +COMMAND_RENAME_VOLUME = "rename-volume" +COMMAND_RUN_SERVER_SERVICE = "run-server-service" +COMMAND_SET_VOLUME_USER_PASSWORD = "set-volume-user-password" +COMMAND_STOP_PARTITION_MIGRATION = "stop-partition-migration" +COMMAND_STOP_VOLUME_SERVER_PARTITION_MIGRATION = "stop-volume-server-partition-migration" +COMMAND_GET_SERVER_DISK_INFO = "get-server-disk-info" +COMMAND_INITIALIZE_SERVER_DISK = "initialize-server-disk" +COMMAND_SET_SERVER_COUNT = "set-server-count" +COMMAND_GET_SERVER_COUNT = "get-server-count" diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Common.py b/src/com.gluster.storage.management.gateway.scripts/src/Common.py new file mode 100644 index 00000000..c85e9a2b --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Common.py @@ -0,0 +1,20 @@ +# Copyright (c) 2009 Gluster, Inc. +# This file is part of GlusterSP. +# +# GlusterSP is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# GlusterSP 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Disk.py b/src/com.gluster.storage.management.gateway.scripts/src/Disk.py new file mode 100755 index 00000000..2c47d396 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Disk.py @@ -0,0 +1,140 @@ +# Copyright (c) 2009 Gluster, Inc. +# This file is part of GlusterSP. +# +# GlusterSP is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# GlusterSP 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import dbus + +class Disk: + def __init__(self): + """init""" + + self.volumes = [] + self.disks = [] + self.bus = dbus.SystemBus() + self.hal_obj = self.bus.get_object("org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager") + self.hal = dbus.Interface(self.hal_obj, "org.freedesktop.Hal.Manager") + self.devices = [] + self.devices = self.hal.FindDeviceByCapability("storage") + + self.detect_disks() + self.detect_mountable_volumes() + + def getDiskList(self): + + return self.disks + + def getMountableDiskList(self): + + return self.volumes + + def detect_disks(self): + for device in self.devices: + dev = self._get_device(device) + if dev.GetProperty("storage.drive_type") != "cdrom": + if not dev.GetProperty("block.is_volume"): + self._add_disks(dev) + continue + + def _add_disks(self, dev): + disk = str(dev.GetProperty('block.device')) + disk_size = str(int(dev.GetProperty('storage.size')) / 1024**2) + + try: + if dev.GetProperty('storage.removable'): + disk_size = str(int(dev.GetProperty('storage.removable.media_size')) / 1024**2) + except: + return + + self.disks.append({ + 'device': disk, + 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')), + 'interface': str(dev.GetProperty('storage.bus')), + 'size': disk_size, + 'drive_type': str(dev.GetProperty('storage.drive_type')) + }) + + def detect_mountable_volumes(self): + """ Detect all mountable volumes using HAL via D-Bus """ + for device in self.devices: + dev = self._get_device(device) + if dev.GetProperty("storage.drive_type") != "cdrom": + if dev.GetProperty("block.is_volume"): + self._add_volume(dev) + continue + else: # iterate over children looking for a volume + children = self.hal.FindDeviceStringMatch("info.parent", + device) + if not children and "disk" == dev.GetProperty("storage.drive_type"): + self._add_volume(dev) + for child in children: + child = self._get_device(child) + if child.GetProperty("block.is_volume"): + self._add_volume(child, parent=dev) + #break # don't break, allow all partitions + + def _add_volume(self, dev, parent=None): + volume = str(dev.GetProperty('block.device')) + if not parent: + self.volumes.append ({ + 'device' : volume, + 'label' : str(dev.GetProperty('block.device')), + 'fstype' : None, + 'fsversion': None, + 'uuid' : None, + 'interface': str(dev.GetProperty('storage.bus')), + 'parent' : None, + 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')), + 'size' : None, + 'totalsize' : str(int(dev.GetProperty('storage.size')) / 1024**2), + 'drive_type': str(dev.GetProperty('storage.drive_type')), + 'mount_point': "NA" + }) + return + + self.volumes.append ({ + 'device' : volume, + 'label' : str(dev.GetProperty('volume.label')), + 'fstype' : str(dev.GetProperty('volume.fstype')), + 'fsversion': str(dev.GetProperty('volume.fsversion')), + 'uuid' : str(dev.GetProperty('volume.uuid')), + 'interface': str(parent.GetProperty('storage.bus')), + 'parent' : str(parent.GetProperty('block.device')), + 'description': str(parent.GetProperty('storage.model')) + " " + str(parent.GetProperty('storage.vendor')), + 'size' : str(int(dev.GetProperty('volume.size')) / 1024**2), + 'totalsize' : str(int(parent.GetProperty('storage.size')) / 1024**2), + 'drive_type': str(parent.GetProperty('storage.drive_type')), + 'mount_point': str(dev.GetProperty('volume.mount_point')) + }) + return + + def _get_device(self, udi): + """ Return a dbus Interface to a specific HAL device UDI """ + dev_obj = self.bus.get_object("org.freedesktop.Hal", udi) + return dbus.Interface(dev_obj, "org.freedesktop.Hal.Device") + + def get_free_bytes(self, device=None): + """ Return the number of available bytes on our device """ + import statvfs + stat = os.statvfs(device) + return stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] + + def get_used_bytes(self, device=None): + """ Return the number of used bytes on our device """ + import statvfs + stat = os.statvfs(device) + return ((stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]) - (stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL])) diff --git a/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py new file mode 100644 index 00000000..4fadc71a --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/DiskUtils.py @@ -0,0 +1,948 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import glob +from copy import deepcopy +import dbus +import Globals +import time +import Utils +import Disk +import Protocol +from FsTabUtils import * + +ONE_MB_SIZE = 1048576 + + +def _stripDev(device): + if Utils.isString(device) and device.startswith("/dev/"): + return device[5:] + return device + + +def _addDev(deviceName): + if Utils.isString(deviceName) and not deviceName.startswith("/dev/"): + return "/dev/" + deviceName + return deviceName + + +def getDeviceName(device): + if type(device) == type([]): + nameList = [] + for d in device: + nameList.append(_stripDev(d)) + return nameList + return _stripDev(device) + + +def getDevice(deviceName): + if Utils.isString(deviceName): + return _addDev(deviceName) + if type(deviceName) == type([]): + nameList = [] + for d in deviceName: + nameList.append(_addDev(d)) + return nameList + return _addDev(deviceName) + + +def getDiskPartitionByUuid(uuid): + uuidFile = "/dev/disk/by-uuid/%s" % uuid + if os.path.exists(uuidFile): + return getDeviceName(os.path.realpath(uuidFile)) + return None + + +def getUuidByDiskPartition(device): + for uuidFile in glob.glob("/dev/disk/by-uuid/*"): + if os.path.realpath(uuidFile) == device: + return os.path.basename(uuidFile) + return None + + +def getDiskPartitionUuid(partition): + Utils.log("WARNING: getDiskPartitionUuid() is deprecated by getUuidByDiskPartition()") + return getUuidByDiskPartition(partition) + + +def getDiskPartitionByLabel(label): + ## TODO: Finding needs to be enhanced + labelFile = "/dev/disk/by-label/%s" % label + if os.path.exists(labelFile): + if os.path.islink(labelFile): + return getDeviceName(os.path.realpath(labelFile)) + return None + + +def getDeviceByLabel(label): + Utils.log("WARNING: getDeviceByLabel() is deprecated by getDiskPartitionByLabel()") + return getDiskPartitionByLabel(label) + + +def getDiskPartitionLabel(device): + rv = Utils.runCommandFG(["sudo", "e2label", device], stdout=True) + if rv["Status"] == 0: + return rv["Stdout"].strip() + return False + + +def readFile(fileName): + lines = None + try: + fp = open(fileName) + lines = fp.readlines() + fp.close() + except IOError, e: + Utils.log("failed to read file %s: %s" % (file, str(e))) + return lines + + +def getRootPartition(fsTabFile=Globals.FSTAB_FILE): + fsTabEntryList = readFsTab(fsTabFile) + for fsTabEntry in fsTabEntryList: + if fsTabEntry["MountPoint"] == "/": + if fsTabEntry["Device"].startswith("UUID="): + return getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1]) + if fsTabEntry["Device"].startswith("LABEL="): + partitionName = getDiskPartitionByLabel(fsTabEntry["Device"].split("LABEL=")[-1]) + if partitionName: + return partitionName + return getDeviceName(fsTabEntry["Device"]) + return None + +def getMounts(): + mounts = {} + for line in readFile("/proc/mounts"): + str = line.strip() + if str.startswith("/dev/"): + tokens = str.split() + device = {} + mountPoint = tokens[1].strip() + device["MountPoint"] = mountPoint + device["FsType"] = tokens[2].strip() + device["Uuid"] = getDiskPartitionUuid(tokens[0].strip()) + device["Status"] = "INITIALIZED" + if mountPoint: + if "/export/" in mountPoint: + device["Type"] = "DATA" + else: + device["Type"] = "BOOT" + else: + device["Type"] = "UNKNOWN" + mounts[tokens[0].strip()] = device + return mounts + +def getRaidDisk(): + array = [] + arrayList = [] + mdFound = False + + try: + fp = open("/proc/mdstat") + for line in fp: + str = line.strip() + if str.startswith("md"): + array.append(str) + mdFound = True + continue + if mdFound: + if str: + array.append(str) + else: + arrayList.append(array) + array = [] + mdFound = False + fp.close() + except IOError, e: + return None + + raidList = {} + for array in arrayList: + raid = {} + tokens = array[0].split() + raid['Interface'] = tokens[3] + device = getDevice(tokens[0]) + raid['MountPoint'] = getDeviceMountPoint(device) + if raid['MountPoint']: + if "/export/" in raid['MountPoint']: + raid['Type'] = "DATA" + else: + raid['Type'] = "BOOT" + else: + raid['Type'] = "UNKNOWN" + rv = Utils.runCommand("blkid -c /dev/null %s" % (device), output=True, root=True) + raid['Uuid'] = None + raid['FsType'] = None + raid['Status'] = "UNINITIALIZED" + if isDiskInFormatting(device): + raid['Status'] = "INITIALIZING" + if not rv["Stderr"]: + words = rv["Stdout"].strip().split() + if words: + raid['Status'] = "INITIALIZED" + if len(words) > 2: + raid['Uuid'] = words[1].split("UUID=")[-1].split('"')[1] + raid['FsType'] = words[2].split("TYPE=")[-1].split('"')[1] + + used = 0 + rv = Utils.runCommand("df %s" % (device), output=True, root=True) + if rv["Status"] == 0: + try: + used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024 + except IndexError: + pass + except ValueError: + pass + raid['SpaceInUse'] = used + raid['Disks'] = [x.split('[')[0] for x in tokens[4:]] + raid['Size'] = float(array[1].split()[0]) / 1024.0 + raidList[tokens[0]] = raid + return raidList + + +def getOsDisk(): + Utils.log("WARNING: getOsDisk() is deprecated by getRootPartition()") + return getRootPartition() + + +def getDiskInfo(diskDeviceList=None): + diskDeviceList = getDevice(diskDeviceList) + if Utils.isString(diskDeviceList): + diskDeviceList = [diskDeviceList] + + mounts = getMounts() + if Utils.runCommand("/usr/bin/lshal") != 0: + Utils.log("failed running /usr/bin/lshal") + + dbusSystemBus = dbus.SystemBus() + halObj = dbusSystemBus.get_object("org.freedesktop.Hal", + "/org/freedesktop/Hal/Manager") + halManager = dbus.Interface(halObj, "org.freedesktop.Hal.Manager") + storageUdiList = halManager.FindDeviceByCapability("storage") + + diskInfo = {} + diskList = [] + for udi in storageUdiList: + halDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal", udi) + halDevice = dbus.Interface(halDeviceObj, + "org.freedesktop.Hal.Device") + if halDevice.GetProperty("storage.drive_type") in ["cdrom", "floppy"] or \ + halDevice.GetProperty("block.is_volume"): + continue + disk = {} + disk["Device"] = str(halDevice.GetProperty('block.device')) + if diskDeviceList and disk["Device"] not in diskDeviceList: + continue + disk["Description"] = str(halDevice.GetProperty('storage.vendor')) + " " + str(halDevice.GetProperty('storage.model')) + if halDevice.GetProperty('storage.removable'): + disk["Size"] = long(halDevice.GetProperty('storage.removable.media_size')) + else: + disk["Size"] = long(halDevice.GetProperty('storage.size')) / 1024**2 + disk["Interface"] = str(halDevice.GetProperty('storage.bus')) + disk["DriveType"] = str(halDevice.GetProperty('storage.drive_type')) + disk["Status"] = None + disk["Uuid"] = None + disk["Init"] = False + disk["Type"] = None + disk["FsType"] = None + disk["FsVersion"] = None + disk["MountPoint"] = None + disk["ReadOnlyAccess"] = None + disk["SpaceInUse"] = None + + partitionUdiList = halManager.FindDeviceStringMatch("info.parent", udi) + if isDiskInFormatting(disk["Device"]): + disk["Status"] = "INITIALIZING" + else: + if partitionUdiList: + disk["Status"] = "INITIALIZED" + else: + disk["Status"] = "UNINITIALIZED" + disk["Type"] = "UNKNOWN" + + if mounts and mounts.has_key(disk["Device"]): + disk["Uuid"] = mounts[disk["Device"]]["Uuid"] + disk["Type"] = mounts[disk["Device"]]["Type"] + disk["Status"] = mounts[disk["Device"]]["Status"] + disk["FsType"] = mounts[disk["Device"]]["FsType"] + disk["MountPoint"] = mounts[disk["Device"]]["MountPoint"] + + partitionList = [] + diskSpaceInUse = 0 + for partitionUdi in partitionUdiList: + used = 0 + partitionHalDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal", + partitionUdi) + partitionHalDevice = dbus.Interface(partitionHalDeviceObj, + "org.freedesktop.Hal.Device") + if not partitionHalDevice.GetProperty("block.is_volume"): + continue + partitionDevice = str(partitionHalDevice.GetProperty('block.device')) + if partitionHalDevice.GetProperty("volume.is_mounted"): + rv = Utils.runCommandFG(["df", str(partitionHalDevice.GetProperty('volume.mount_point'))], stdout=True) + if rv["Status"] == 0: + try: + used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024 + diskSpaceInUse += used + except IndexError: + pass + except ValueError: + pass + + if disk["Device"] == partitionDevice: + disk["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid')) + disk["Init"] = True # TODO: use isDataDiskPartitionFormatted function to cross verify this + disk["Status"] = "INITIALIZED" + mountPoint = str(partitionHalDevice.GetProperty('volume.mount_point')) + if mountPoint: + if "/export/" in mountPoint: + disk["Type"] = "DATA" + else: + disk["Type"] = "BOOT" + else: + disk["Type"] = "UNKNOWN" + disk["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype')) + if disk["FsType"] and "UNINITIALIZED" == disk["Status"]: + disk["Status"] = "INITIALIZED" + disk["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion')) + disk["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point')) + disk["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only')) + if not disk["Size"]: + disk["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 + disk["SpaceInUse"] = used + continue + + partition = {} + partition["Init"] = False + partition["Type"] = "UNKNOWN" + partition["Device"] = partitionDevice + partition["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid')) + partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 + partition["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype')) + partition["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion')) + partition["Label"] = str(partitionHalDevice.GetProperty('volume.label')) + partition["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point')) + partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 + + if isDiskInFormatting(partitionDevice): + partition["Status"] = "INITIALIZING" + else: + if partition["FsType"]: + partition["Status"] = "INITIALIZED" + else: + partition["Status"] = "UNINITIALIZED" + + partition["SpaceInUse"] = used + if partition["MountPoint"] or isDataDiskPartitionFormatted(partitionDevice): + partition["Init"] = True + partition["Status"] = "INITIALIZED" + if partition["MountPoint"]: + if "/export/" in partition["MountPoint"]: + partition["Type"] = "DATA" + else: + partition["Type"] = "BOOT" + else: + if "SWAP" == partition["FsType"].strip().upper(): + partition["Type"] = "SWAP" + partition["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only')) + partitionList.append(partition) + disk["Partitions"] = partitionList + if not disk["SpaceInUse"]: + disk["SpaceInUse"] = diskSpaceInUse + diskList.append(disk) + diskInfo["disks"] = diskList + if diskList: + return diskInfo + for line in readFile("/proc/partitions")[2:]: + disk = {} + tokens = line.split() + if tokens[3].startswith("md"): + continue + disk["Device"] = tokens[3] + ## if diskDeviceList and disk["Device"] not in diskDeviceList: + ## continue + disk["Description"] = None + disk["Size"] = long(tokens[2]) / 1024 + disk["Status"] = None + disk["Interface"] = None + disk["DriveType"] = None + disk["Uuid"] = None + disk["Init"] = False + disk["Type"] = None + disk["FsType"] = None + disk["FsVersion"] = None + disk["MountPoint"] = None + disk["ReadOnlyAccess"] = None + disk["SpaceInUse"] = None + disk["Partitions"] = [] + diskList.append(disk) + diskInfo["disks"] = diskList + return diskInfo + +def getDiskList(diskDeviceList=None): + return diskInfo["disks"] + +def readFsTab(fsTabFile=Globals.FSTAB_FILE): + try: + fsTabfp = open(fsTabFile) + except IOError, e: + Utils.log("readFsTab(): " + str(e)) + return None + + fsTabEntryList = [] + for line in fsTabfp: + tokens = line.strip().split() + if not tokens or tokens[0].startswith('#'): + continue + fsTabEntry = {} + fsTabEntry["Device"] = None + fsTabEntry["MountPoint"] = None + fsTabEntry["FsType"] = None + fsTabEntry["Options"] = None + fsTabEntry["DumpOption"] = 0 + fsTabEntry["fsckOrder"] = 0 + try: + fsTabEntry["Device"] = tokens[0] + fsTabEntry["MountPoint"] = tokens[1] + fsTabEntry["FsType"] = tokens[2] + fsTabEntry["Options"] = tokens[3] + fsTabEntry["DumpOption"] = tokens[4] + fsTabEntry["fsckOrder"] = tokens[5] + except IndexError: + pass + if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]: + fsTabEntryList.append(fsTabEntry) + fsTabfp.close() + return fsTabEntryList + + +def checkDiskMountPoint(diskMountPoint): + try: + fstabEntries = open(Globals.FSTAB_FILE).readlines() + except IOError: + fstabEntries = [] + found = False + for entry in fstabEntries: + entry = entry.strip() + if not entry: + continue + entries = entry.split() + if entries and len(entries) > 1 and entries[0].startswith("UUID=") and entries[1].upper() == diskMountPoint.upper(): + return True + return False + + +def getMountPointByUuid(partitionUuid): + # check uuid in etc/fstab + try: + fstabEntries = open(Globals.FSTAB_FILE).readlines() + except IOError: + fstabEntries = [] + found = False + for entry in fstabEntries: + entry = entry.strip() + if not entry: + continue + if entry.split()[0] == "UUID=" + partitionUuid: + return entry.split()[1] + return None + + +def getDiskSizeInfo(partition): + # get values from df output + total = None + used = None + free = None + command = "df -kl -t ext3 -t ext4 -t xfs" + rv = Utils.runCommandFG(command, stdout=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"])) + return None, None, None + for line in rv["Stdout"].split("\n"): + tokens = line.split() + if len(tokens) < 4: + continue + if tokens[0] == partition: + total = int(tokens[1]) / 1024.0 + used = int(tokens[2]) / 1024.0 + free = int(tokens[3]) / 1024.0 + break + + if total: + return total, used, free + + # get total size from parted output + for i in range(len(partition), 0, -1): + pos = i - 1 + if not partition[pos].isdigit(): + break + disk = partition[:pos+1] + partitionNumber = partition[pos+1:] + if not partitionNumber.isdigit(): + return None, None, None + + number = int(partitionNumber) + command = "parted -ms %s unit kb print" % disk + rv = Utils.runCommandFG(command, stdout=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"])) + return None, None, None + + lines = rv["Stdout"].split(";\n") + if len(lines) < 3: + return None,None,None + + for line in lines[2:]: + tokens = line.split(':') + if len(tokens) < 4: + continue + if tokens[0] == str(number): + total = int(tokens[3].split('kB')[0]) / 1024.0 + break + return total, used, free + + +def isDataDiskPartitionFormatted(device): + #Todo: Proper label needs to be added for data partition + #if getDiskPartitionLabel(device) != Globals.DATA_PARTITION_LABEL: + # return False + device = getDeviceName(device) + diskObj = Disk.Disk() + for disk in diskObj.getMountableDiskList(): + if disk['device'].upper() == device.upper(): + mountPoint = disk['mount_point'] + if not mountPoint: + return False + if not os.path.exists(mountPoint): + return False + + uuid = getUuidByDiskPartition(device) + if not uuid: + return False + + for fsTabEntry in readFsTab(): + if fsTabEntry["Device"] == ("UUID=%s" % uuid) and fsTabEntry["MountPoint"] == mountPoint: + return True + return False + + +def getDiskDom(diskDeviceList=None, bootPartition=None, skipDisk=None): + diskDeviceList = getDevice(diskDeviceList) + if Utils.isString(diskDeviceList): + diskDeviceList = [diskDeviceList] + + if skipDisk: + skipDisk = getDevice(skipDisk) + if Utils.isString(skipDisk): + skipDisk = [skipDisk] + + diskInfo = getDiskInfo(diskDeviceList) + diskList = diskInfo["disks"] + if not diskList: + return None + + raidPartitions = {} + raidDisk = getRaidDisk() + + for k, v in raidDisk.iteritems(): + for i in v['Disks']: + raidPartitions[i] = k + + #for partition in raidDisk.values(): + # raidDiskPartitions += partition['disks'] + + diskDom = Protocol.XDOM() + disksTag = diskDom.createTag("disks", None) + raidDisks = {} + if not bootPartition: + bootPartition = getRootPartition() + for disk in diskList: + if skipDisk and disk["Device"] in skipDisk: + continue + diskTag = diskDom.createTag("disk", None) + diskDevice = getDeviceName(disk["Device"]) + diskTag.appendChild(diskDom.createTag("name", diskDevice)) + diskTag.appendChild(diskDom.createTag("description", disk["Description"])) + diskTag.appendChild(diskDom.createTag("uuid", disk["Uuid"])) + diskTag.appendChild(diskDom.createTag("status", disk["Status"])) + diskTag.appendChild(diskDom.createTag("interface", disk["Interface"])) + + #if not disk["Partitions"]: + diskTag.appendChild(diskDom.createTag("type", disk["Type"])) + #diskTag.appendChild(diskDom.createTag("init", str(disk["Init"]).lower())) + diskTag.appendChild(diskDom.createTag("fsType", disk["FsType"])) + diskTag.appendChild(diskDom.createTag("fsVersion", disk["FsVersion"])) + diskTag.appendChild(diskDom.createTag("mountPoint", disk["MountPoint"])) + + diskTag.appendChild(diskDom.createTag("size", disk["Size"])) + diskTag.appendChild(diskDom.createTag("spaceInUse", disk["SpaceInUse"])) + partitionsTag = diskDom.createTag("partitions", None) + if raidPartitions.has_key(diskDevice): + rdList = {} + rdList[diskDevice] = [deepcopy(diskTag)] + if not raidDisks.has_key(raidPartitions[diskDevice]): + raidDisks[raidPartitions[diskDevice]] = [] + raidDisks[raidPartitions[diskDevice]] += [rdList] + continue + for partition in disk["Partitions"]: + partitionTag = diskDom.createTag("partition", None) + device = getDeviceName(partition["Device"]) + partitionTag.appendChild(diskDom.createTag("name", device)) + if partition["Uuid"]: #TODO: Move this verification and findings to getDiskInfo function + partitionTag.appendChild(diskDom.createTag("uuid", partition["Uuid"])) + else: + partitionTag.appendChild(diskDom.createTag("uuid", getUuidByDiskPartition("/dev/" + device))) + partitionTag.appendChild(diskDom.createTag("status", partition["Status"])) + #partitionTag.appendChild(diskDom.createTag("init", str(partition["Init"]).lower())) + partitionTag.appendChild(diskDom.createTag("type", str(partition["Type"]))) + partitionTag.appendChild(diskDom.createTag("fsType", partition["FsType"])) + partitionTag.appendChild(diskDom.createTag("mountPoint", partition['MountPoint'])) + partitionTag.appendChild(diskDom.createTag("size", partition["Size"])) + partitionTag.appendChild(diskDom.createTag("spaceInUse", partition["SpaceInUse"])) + if raidPartitions.has_key(device): + tempPartitionTag = diskDom.createTag("partitions", None) + if raidDisks.has_key(raidPartitions[device]): + rdList = raidDisks[raidPartitions[device]] + for rdItem in rdList: + if not rdItem.has_key(diskDevice): + rdItem[diskDevice] = [deepcopy(diskTag), tempPartitionTag] + rdItem[diskDevice][0].appendChild(tempPartitionTag) + rdItem[diskDevice][-1].appendChild(partitionTag) + continue + rdList = {} + rdList[diskDevice] = [deepcopy(diskTag), tempPartitionTag] + tempPartitionTag.appendChild(partitionTag) + rdList[diskDevice][0].appendChild(tempPartitionTag) + raidDisks[raidPartitions[device]] = [rdList] + continue + partitionsTag.appendChild(partitionTag) + diskTag.appendChild(partitionsTag) + disksTag.appendChild(diskTag) + + for rdisk in raidDisk.keys(): + raidDiskTag = diskDom.createTag("disk", None) + raidDiskTag.appendChild(diskDom.createTag("name", rdisk)) + raidDiskTag.appendChild(diskDom.createTag("description")) + raidDiskTag.appendChild(diskDom.createTag("uuid", raidDisk[rdisk]['Uuid'])) + raidDiskTag.appendChild(diskDom.createTag("type", raidDisk[rdisk]['Type'])) + raidDiskTag.appendChild(diskDom.createTag("mountPoint", raidDisk[rdisk]['MountPoint'])) + raidDiskTag.appendChild(diskDom.createTag("status", raidDisk[rdisk]['Status'])) + raidDiskTag.appendChild(diskDom.createTag("interface", raidDisk[rdisk]['Interface'])) + raidDiskTag.appendChild(diskDom.createTag("fsType", raidDisk[rdisk]['FsType'])) + raidDiskTag.appendChild(diskDom.createTag("fsVersion")) + raidDiskTag.appendChild(diskDom.createTag("size", raidDisk[rdisk]['Size'])) + raidDiskTag.appendChild(diskDom.createTag("spaceInUse", raidDisk[rdisk]['SpaceInUse'])) + raidDisksTag = diskDom.createTag("raidDisks", None) + if raidDisks.has_key(rdisk): + for item in raidDisks[rdisk]: + for diskTag in item.values(): + raidDisksTag.appendChild(diskTag[0]) + raidDiskTag.appendChild(raidDisksTag) + disksTag.appendChild(raidDiskTag) + diskDom.addTag(disksTag) + return diskDom + + +def initializeDisk(disk, boot=False, startSize=0, sudo=False): + if boot and startSize > 0: + return False + + disk = getDevice(disk) + diskObj = getDiskList(disk)[0] + + if boot or startSize == 0: + command = "dd if=/dev/zero of=%s bs=1024K count=1" % diskObj["Device"] + if runCommandFG(command, root=sudo) != 0: + if boot: + Utils.log("failed to clear boot sector of disk %s" % diskObj["Device"]) + return False + Utils.log("failed to clear boot sector of disk %s. ignoring" % diskObj["Device"]) + + command = "parted -s %s mklabel gpt" % diskObj["Device"] + if runCommandFG(command, root=sudo) != 0: + return False + + if boot: + command = "parted -s %s mkpart primary ext3 0MB %sMB" % (diskObj["Device"], Globals.OS_PARTITION_SIZE) + if runCommandFG(command, root=sudo) != 0: + return False + command = "parted -s %s set 1 boot on" % (diskObj["Device"]) + if runCommandFG(command, root=sudo) != 0: + return False + startSize = Globals.OS_PARTITION_SIZE + + size = (diskObj["Size"] / ONE_MB_SIZE) - startSize + while size > Globals.MAX_PARTITION_SIZE: + endSize = startSize + Globals.MAX_PARTITION_SIZE + command = "parted -s %s mkpart primary ext3 %sMB %sMB" % (diskObj["Device"], startSize, endSize) + if runCommandFG(command, root=sudo) != 0: + return False + size -= Globals.MAX_PARTITION_SIZE + startSize = endSize + + if size: + command = "parted -s %s mkpart primary ext3 %sMB 100%%" % (diskObj["Device"], startSize) + if runCommandFG(command, root=sudo) != 0: + return False + + if runCommandFG("udevadm settle", root=sudo) != 0: + if runCommandFG("udevadm settle", root=sudo) != 0: + Utils.log("udevadm settle for disk %s failed. ignoring" % diskObj["Device"]) + time.sleep(1) + + if runCommandFG("partprobe %s" % diskObj["Device"], root=sudo) != 0: + Utils.log("partprobe %s failed" % diskObj["Device"]) + return False + + if runCommandFG("gptsync %s" % diskObj["Device"], root=sudo) != 0: + Utils.log("gptsync %s failed. ignoring" % diskObj["Device"]) + + # wait forcefully to appear devices in /dev + time.sleep(2) + return True + + +def initializeOsDisk(diskObj): + Utils.log("WARNING: initializeOsDisk() is deprecated by initializeDisk(boot=True)") + return initializeDisk(diskObj, boot=True) + + +def initializeDataDisk(diskObj): + Utils.log("WARNING: initializeDataDisk() is deprecated by initializeDisk()") + return initializeDisk(diskObj) + +def getBootPartition(serverName): + diskDom = XDOM() + diskDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + if not diskDom: + return None + partitionDom = XDOM() + partitionUuid = None + partitionName = None + for partitionTag in diskDom.getElementsByTagRoute("disk.partition"): + partitionDom.setDomObj(partitionTag) + boot = partitionDom.getTextByTagRoute("boot") + if boot and boot.strip().upper() == 'YES': + partitionUuid = partitionDom.getTextByTagRoute("uuid") + partitionName = partitionDom.getTextByTagRoute("device") + break + if not (partitionUuid and partitionName): + return None + + # check device label name + deviceBaseName = os.path.basename(partitionName) + process = runCommandBG(['sudo', 'e2label', partitionName]) + if type(process) == type(True): + return None + if process.wait() != 0: + return None + output = process.communicate() + deviceLabel = output[0].split()[0] + if deviceLabel != Globals.BOOT_PARTITION_LABEL: + return None + + # check uuid in etc/fstab + try: + fstabEntries = open(Globals.FSTAB_FILE).readlines() + except IOError: + fstabEntries = [] + found = False + for entry in fstabEntries: + entry = entry.strip() + if not entry: + continue + if entry.split()[0] == "UUID=" + partitionUuid: + found = True + break + if not found: + return None + return partitionName + + +def isDiskInFormatting(device): + DEVICE_FORMAT_LOCK_FILE = "/var/lock/%s.lock" % device + return os.path.exists(DEVICE_FORMAT_LOCK_FILE) + + +def isDiskInFormat(device): + Utils.log("WARNING: isDiskInFormat() is deprecated by isDataDiskPartitionFormatted()") + return isDataDiskPartitionFormatted(device) + + +def diskOrder(serverExportList): + newServerExportList = [] + while serverExportList: + serverExport = deepcopy(serverExportList[0]) + if newServerExportList and serverExport.split(":")[0] == newServerExportList[-1].split(":")[0]: + inserted = False + for i in range(0, len(newServerExportList) - 1): + if serverExport.split(":")[0] == newServerExportList[i].split(":")[0]: + continue + if i == 0: + newServerExportList.insert(i, serverExport) + inserted = True + break + if serverExport.split(":")[0] == newServerExportList[i - 1].split(":")[0]: + continue + newServerExportList.insert(i, serverExport) + inserted = True + break + if not inserted: + newServerExportList.append(serverExport) + else: + newServerExportList.append(serverExport) + serverExportList.remove(serverExport) + i = 0 + while serverExportList and i < len(serverExportList): + if serverExport.split(":")[0] == serverExportList[i].split(":")[0]: + i += 1 + continue + serverExport = deepcopy(serverExportList[i]) + newServerExportList.append(serverExport) + serverExportList.remove(serverExport) + return newServerExportList + + +def updateServerDiskConfig(serverName, diskDom, requestFlag=True, partitionFlag=True): + command = "command.server." + if not requestFlag: + command = "" + diskList = {} + for tagE in diskDom.getElementsByTagRoute(command + "disk"): + diskList[diskDom.getTextByTagRoute(command + "device")] = tagE + configDom = XDOM() + if not configDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): + return diskDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + diskTag = configDom.getElementsByTagRoute("disks.disk") + disks = configDom.getElementsByTagRoute("disks") + if not (diskTag or disks): + return None + for tagE in diskTag: + diskDom = XDOM() + diskDom.setDomObj(tagE) + device = diskDom.getTextByTagRoute("device") + if partitionFlag and device in diskList: + disks[0].removeChild(tagE) + disks[0].appendChild(deepcopy(diskList[device])) + continue + if not partitionFlag and device in diskList: + partitionList = [] + for childNodeTag in tagE.childNodes: + if childNodeTag.nodeName == 'partition': + partitionList.append(childNodeTag) + tagE.childNodes = [] + tagE.childNodes = diskList[device].childNodes + partitionList + return configDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + + +def compareDisksDom(diskDomA, diskDomB, requestFlag=True): + command = "command.server.disk." + if not requestFlag: + command = "" + sourceDiskList = {} + sourceDisk = {} + for tagE in diskDomA.getElementsByTagRoute("disk"): + sourceDisk["description"] = diskDomA.getTextByTagRoute("description") + sourceDisk["size"] = diskDomA.getTextByTagRoute("size") + sourceDisk["init"] = diskDomA.getTextByTagRoute("init") + sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface") + sourceDiskList[diskDomA.getTextByTagRoute("device")] = sourceDisk + objDiskList = {} + objDisk = {} + for tagE in diskDomB.getElementsByTagRoute("disk"): + objDisk["description"] = diskDomB.getTextByTagRoute("description") + objDisk["size"] = diskDomB.getTextByTagRoute("size") + objDisk["init"] = diskDomB.getTextByTagRoute("init") + objDisk["interface"] = diskDomB.getTextByTagRoute("interface") + objDiskList[diskDomB.getTextByTagRoute("device")] = objDisk + return sourceDiskList == objDiskList + + +def compareDiskDom(diskDomA, diskDomB, requestFlag=True): + command = "command.server.disk." + if not requestFlag: + command = "" + sourceDisk = {} + sourceDisk["device"] = diskDomA.getTextByTagRoute("device") + sourceDisk["description"] = diskDomA.getTextByTagRoute("description") + sourceDisk["size"] = diskDomA.getTextByTagRoute("size") + sourceDisk["init"] = diskDomA.getTextByTagRoute("init") + sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface") + for tagE in diskDomA.getElementsByTagRoute("partition"): + sourceDiskPartitions = {} + partitionDom = XDOM() + partitionDom.setDomObj(tagE) + sourceDiskPartitions["size"] = partitionDom.getTextByTagRoute("size") + #sourceDiskPartitions["free"] = partitionDom.getTextByTagRoute("free") + sourceDiskPartitions["format"] = partitionDom.getTextByTagRoute("format") + sourceDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid") + sourceDisk[partitionDom.getTextByTagRoute("device")] = sourceDiskPartitions + + objDisk = {} + objDisk["device"] = diskDomB.getTextByTagRoute(command + "device") + objDisk["description"] = diskDomB.getTextByTagRoute(command + "description") + objDisk["size"] = diskDomB.getTextByTagRoute(command + "size") + objDisk["init"] = diskDomB.getTextByTagRoute(command + "init") + objDisk["interface"] = diskDomB.getTextByTagRoute(command + "interface") + for tagE in diskDomB.getElementsByTagRoute(command + "partition"): + objDiskPartitions = {} + partitionDom = XDOM() + partitionDom.setDomObj(tagE) + objDiskPartitions["size"] = partitionDom.getTextByTagRoute("size") + #objDiskPartitions["free"] = partitionDom.getTextByTagRoute("free") + objDiskPartitions["format"] = partitionDom.getTextByTagRoute("format") + objDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid") + objDisk[partitionDom.getTextByTagRoute("device")] = objDiskPartitions + return sourceDisk == objDisk + + +def getServerConfigDiskDom(serverName, diskName=None): + diskConfigDom = XDOM() + if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): + Utils.log("Unable to parse %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + return None + diskTag = diskConfigDom.getElementsByTagRoute("disks.disk") + if not diskTag: + Utils.log("Unable to reterive disk information %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + return None + if diskName: + for tagE in diskTag: + diskDom = XDOM() + diskDom.setDomObj(tagE) + if diskName == diskDom.getTextByTagRoute("device"): + return diskDom + return None + + for tagE in diskTag: + for partitionTag in tagE.getElementsByTagName("partition"): + tagE.removeChild(partitionTag) + return diskConfigDom + + +def getDeviceMountPoint(device): + try: + fp = open("/proc/mounts") + for token in [line.strip().split() for line in fp.readlines()]: + if token and len(token) > 2 and token[0] == device: + return token[1] + fp.close() + except IOError, e: + return None + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py new file mode 100644 index 00000000..fcac4196 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/FsTabUtils.py @@ -0,0 +1,92 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import Globals + +def readFsTab(fsTabFile=Globals.FSTAB_FILE): + try: + fsTabfp = open(fsTabFile) + except IOError, e: + log("readFsTab(): " + str(e)) + return None + + fsTabEntryList = [] + for line in fsTabfp: + tokens = line.strip().split() + if not tokens or tokens[0].startswith('#'): + continue + fsTabEntry = {} + fsTabEntry["Device"] = None + fsTabEntry["MountPoint"] = None + fsTabEntry["FsType"] = None + fsTabEntry["Options"] = None + fsTabEntry["DumpOption"] = 0 + fsTabEntry["fsckOrder"] = 0 + try: + fsTabEntry["Device"] = tokens[0] + fsTabEntry["MountPoint"] = tokens[1] + fsTabEntry["FsType"] = tokens[2] + fsTabEntry["Options"] = tokens[3] + fsTabEntry["DumpOption"] = tokens[4] + fsTabEntry["fsckOrder"] = tokens[5] + except IndexError: + pass + if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]: + fsTabEntryList.append(fsTabEntry) + + fsTabfp.close() + return fsTabEntryList + +def writeFsTab(fsTabEntryList, fsTabFile=Globals.FSTAB_FILE): + try: + fsTabfp = open(fsTabFile, "w") + for fsTabEntry in fsTabEntryList: + fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" % + (fsTabEntry["Device"], fsTabEntry["MountPoint"], + fsTabEntry["FsType"], fsTabEntry["Options"], + fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"])) + fsTabfp.close() + except IOError, e: + log("writeFsTab(): " + str(e)) + return False + return True + +def addFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE): + try: + fsTabfp = open(fsTabFile, "a") + fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" % + (fsTabEntry["Device"], fsTabEntry["MountPoint"], + fsTabEntry["FsType"], fsTabEntry["Options"], + fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"])) + fsTabfp.close() + except IOError, e: + log("addFsTabEntry(): " + str(e)) + return False + return True + +def removeFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE): + fsTabEntryList = readFsTab(fsTabFile) + if not fsTabEntryList: + return False + + try: + fsTabEntryList.remove(fsTabEntry) + except ValueError: + return False + + return writeFsTab(fsTabEntryList, fsTabFile) + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py b/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py new file mode 100644 index 00000000..3311eb56 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/GetServerNetworkConfig.py @@ -0,0 +1,96 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import syslog +import Globals +import Commands +import re +from ServerUtils import * +from Protocol import * +from NetworkUtils import * + +def getServerNetworkConfig(requestXml): + serverName = requestXml.getTextByTagRoute("command.server-name") + version = requestXml.getVersion() + messageId = requestXml.getAttribute("id") + + if not serverName: + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) + responseDom.appendTagRoute("server.name", serverName) + return responseDom + responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "OK", messageId, version) + serverTag = responseDom.createTag("server", None) + serverTag.appendChild(responseDom.createTag("name", serverName)) + nameServerList, domain, searchDomain = readResolvConfFile() + if domain: + domainName = domain[0] + else: + domainName = None + serverTag.appendChild(responseDom.createTag("domainname", domainName)) + i = 1 + for dns in nameServerList: + serverTag.appendChild(responseDom.createTag("dns%s" % i, dns)) + i += 1 + #TODO: probe and retrieve timezone, ntp-server, preferred-network details and update the tags + configDom = XDOM() + if configDom.parseFile("%s/%s/network.xml" % (Globals.SERVER_CONF_DIR, serverName)): + serverTag.appendChild(responseDom.createTag("timezone", configDom.getTextByTagRoute("network.timezone"))) + serverTag.appendChild(responseDom.createTag("ntp-server", configDom.getTextByTagRoute("network.ntp-server"))) + preferredNetwork = configDom.getTextByTagRoute("network.preferred-network") + if not preferredNetwork: + preferredNetwork = "any" + serverTag.appendChild(responseDom.createTag("preferred-network", preferredNetwork)) + + deviceList = {} + for device in getNetDeviceList(): + deviceList[device["device"]] = device + try: + macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() + except IOError: + continue + interfaceTag = responseDom.createTag("interface", None) + interfaceTag.appendChild(responseDom.createTag("device", device["device"])) + interfaceTag.appendChild(responseDom.createTag("description", device["description"])) + interfaceTag.appendChild(responseDom.createTag("hwaddr", macAddress)) + if deviceList[device["device"]]: + if deviceList[device["device"]]["onboot"]: + interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", deviceList[device["device"]]["bootproto"])) + interfaceTag.appendChild(responseDom.createTag("ipaddr", deviceList[device["device"]]["ipaddr"])) + interfaceTag.appendChild(responseDom.createTag("netmask", deviceList[device["device"]]["netmask"])) + interfaceTag.appendChild(responseDom.createTag("gateway", deviceList[device["device"]]["gateway"])) + if deviceList[device["device"]]["mode"]: + interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) + if deviceList[device["device"]]["master"]: + interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) + spliter = re.compile(r'[\D]') + interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) + else: + interfaceTag.appendChild(responseDom.createTag("onboot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootproto", "none")) + serverTag.appendChild(interfaceTag) + responseDom.appendTag(serverTag) + return responseDom + +def test(): + requestString = """ +s1""" + requestDom = RequestXml(requestString) + print getServerNetworkConfig(requestDom).toxml() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Globals.py b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py new file mode 100644 index 00000000..f8a07c25 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py @@ -0,0 +1,123 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +MULTICAST_GROUP = '224.224.1.1' +MULTICAST_PORT = 5353 +GLUSTER_PLATFORM_VERSION = "3.2" + +## System configuration constants +SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" +DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" + +FSTAB_FILE = "/etc/fstab" +NFS_EXPORTS_FILE = "/etc/exports" +SAMBA_CONF_FILE = "/etc/samba/smb.conf" +TIMEZONE_FILE = "/etc/timezone" +ZONEINFO_DIR = "/usr/share/zoneinfo" +LOCALTIME_FILE = "/etc/localtime" +KERBEROS_CONF_FILE = "/etc/krb5.conf" +NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" +NTP_CONF_FILE = "/etc/ntp.conf" +MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" +SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" +RESOLV_CONF_FILE = "/etc/resolv.conf" +DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" +LIVE_MODE_FILE = "/etc/live" +ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" + +DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" +DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" +## + +## Base constants +MAX_PARTITION_SIZE = 16777216 # 16 TB +OS_PARTITION_SIZE = 4000 # 4 GB +SESSION_TIMEOUT = 1800 # 30 minutes +SERVER_AGENT_PORT = 50000 + +BOOT_PARTITION_LABEL = "GLUSTEROS" +DATA_PARTITION_LABEL = "GLUSTERDATA" +VOLUME_USER_DESCRIPTION = "Gluster Volume User" +SERVER_AGENT_RUN_USERNAME = "gluster" +INSTALLER_SERVER_NAME = "$installer$" + +GLUSTER_BASE_DIR = "/etc/glustermg" +GLUSTER_LUN_DIR = "/data" +REEXPORT_DIR = "/reexport" +NFS_EXPORT_DIR = "/nfs" +CIFS_EXPORT_DIR = "/cifs" +WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" +UPDATES_DIR = "/UPDATES" +TRANSPORT_HOME_DIR = "/transport" +GLUSTERFS_LOG_DIR = "/var/log/glusterfs" +LOG_DIR = "/var/log/glustermg" + +GLUSTER_UPDATES_FILE = "updates.xml" +INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" +INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" +LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" +PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" +## + +## Derived constants +GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" +GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" +VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" +SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" +DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" +INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME + +GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" +GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" +GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" +GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" +GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" +TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" +SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" +SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" +GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" +GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" + +VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" + +GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" +INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" +INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" +INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" + +SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" + +GENERAL_LOG_FILE = LOG_DIR + "/general.log" +INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" +PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log" +SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" +TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" +## + + +## Global variables +## TODO: These should be removed +DOWNLOAD_GLUSTER_UPDATE_PROCESS = None +DOWNLOAD_GLUSTER_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None +REQUEST_MAP = {} +VERSION_DICTONARY = {} +## + +AWS_WEB_SERVICE_URL = "http://169.254.169.254/latest" +REAL_SAMBA_CONF_FILE = "/etc/samba/real.smb.conf" diff --git a/src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py new file mode 100644 index 00000000..7c0e899c --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/GlusterdUtils.py @@ -0,0 +1,250 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import Utils + +import ServerUtils + + +def getGlusterVolumeInfo(volumeName=None): + volumeNameList = None + if Utils.isString(volumeName): + volumeNameList = [volumeName] + if type(volumeName) == type([]): + volumeNameList = volumeName + + status = Utils.runCommand("gluster volume info", output=True, root=True) + if status["Status"] != 0: + Utils.log("Failed to execute 'gluster volume info' command") + return None + + volumeInfoDict = {} + volumeInfo = {} + volumeName = None + brickList = [] + for line in status['Stdout'].split("\n"): + if not line: + if volumeName and volumeInfo: + volumeInfo["Bricks"] = brickList + volumeInfoDict[volumeName] = volumeInfo + volumeInfo = {} + volumeName = None + brickList = [] + continue + + tokens = line.split(":") + if tokens[0].strip().upper() == "BRICKS": + continue + elif tokens[0].strip().upper() == "VOLUME NAME": + volumeName = tokens[1].strip() + volumeInfo["VolumeName"] = volumeName + elif tokens[0].strip().upper() == "TYPE": + volumeInfo["VolumeType"] = tokens[1].strip() + elif tokens[0].strip().upper() == "STATUS": + volumeInfo["VolumeStatus"] = tokens[1].strip() + elif tokens[0].strip().upper() == "TRANSPORT-TYPE": + volumeInfo["TransportType"] = tokens[1].strip() + elif tokens[0].strip().upper().startswith("BRICK"): + brickList.append(":".join(tokens[1:]).strip()) + + if volumeName and volumeInfo: + volumeInfoDict[volumeName] = volumeInfo + + if not volumeNameList: + return volumeInfoDict + + # remove unwanted volume info + for volumeName in list(set(volumeInfoDict.keys()) - set(volumeNameList)): + del volumeInfoDict[volumeName] + + return volumeInfoDict + + +def isVolumeRunning(volumeName): + if not volumeName: + return False + volumeInfo = getGlusterVolumeInfo(volumeName) + if not volumeInfo: + return False + status = volumeInfo[volumeName]["VolumeStatus"] + if not status: + return False + if status.upper() == "STARTED": + return True + return False + + +def isVolumeExist(volumeName): + if not volumeName: + return False + if getGlusterVolumeInfo(volumeName): + return True + return False + + +def peerProbe(serverName): + command = "gluster peer probe %s" % serverName + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def setAuthAllow(volumeName, authList, includeServers=True): + if not (volumeName and authList): + return False + vacl = [] + if includeServers: + for serverName in ServerUtils.getAllServerList(): + vacl += ServerUtils.getServerIpList(serverName) + vacl += authList + + command = "gluster volume set %s auth.allow %s" % (volumeName, ",".join(list(set(vacl)))) + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def volumeCreate(volumeName, volumeType, transportTypeList, brickList): + command = "gluster volume create %s" % volumeName + + if volumeType.upper() == "MIRROR": + command += " replica 2" + elif volumeType.upper() == "STRIPE": + command += " stripe 4" + + if "RDMA" in transportTypeList: + command += " transport rdma" + + command += " " + " ".join(brickList) + + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def volumeDelete(volumeName): + command = "gluster --mode=script volume delete %s" % volumeName + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def volumeLogFileName(volumeName, brick, logDir): + command = "gluster volume log filename %s %s %s" % (volumeName, brick, logDir) + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def startVolumeMigration(volumeName, sourcePath, destinationPath): + command = "gluster volume replace-brick %s %s %s start" % (volumeName, sourcePath, destinationPath) + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if lines[0].split()[-1] == "successfully": + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def stopVolumeMigration(volumeName, sourcePath, destinationPath): + command = "gluster volume replace-brick %s %s %s abort" % (volumeName, sourcePath, destinationPath) + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if lines[0].split()[-1] == "successful": + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def commitVolumeMigration(volumeName, sourcePath, destinationPath): + command = "gluster volume replace-brick %s %s %s commit" % (volumeName, sourcePath, destinationPath) + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if lines[0].split()[-1] == "successful": + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def getMigrationStatus(volumeName, sourcePath, destinationPath): + command = "gluster volume replace-brick %s %s %s status" % (volumeName, sourcePath, destinationPath) + status = Utils.runCommand(command, output=True, root=True) + if status['Status'] == 0 and status['Stdout']: + lines = status["Stdout"].split("\n") + if "Current file" in lines[0]: + return "started" + if "Migration complete" in lines[0]: + return "completed" + Utils.log("command [%s] returns unknown status:%s" % (command, lines[0])) + return "failed" + #if status['Status'] == 0 and status['Stdout']: + # for line in status['Stdout'].split('\n'): + # words = line.split() + # if words and words[0].upper() == "STATUS:": + # return " ".join(words[1:]).upper() + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return None + + +def volumeRebalanceStart(volumeName): + command = "gluster volume rebalance %s start" % volumeName + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if lines[0].split()[-1] == "successful": + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def volumeRebalanceStop(volumeName): + command = "gluster volume rebalance %s stop" % volumeName + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if lines[0].split()[0] == "stopped": + return True + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + + +def volumeRebalanceStatus(volumeName): + command = "gluster volume rebalance %s status" % volumeName + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + lines = status["Stdout"].split("\n") + if "rebalance not started" in lines[0]: + return "not started" + if "rebalance completed" in lines[0]: + return "completed" + return "running" + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False diff --git a/src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py new file mode 100755 index 00000000..42e9892c --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/NetworkUtils.py @@ -0,0 +1,483 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys + +if not "/usr/share/system-config-network/" in sys.path: + sys.path.append("/usr/share/system-config-network") + +import os +import tempfile +import Globals + +from Utils import * +#from netconfpkg.NCHardwareList import getHardwareList + +def readHostFile(fileName=None): + hostEntryList = [] + if not fileName: + fileName = "/etc/hosts" + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + hostEntryList.append({tokens[0] : tokens[1:]}) + return hostEntryList + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeHostFile(hostEntryList, fileName=None): + if fileName: + hostFile = fileName + else: + hostFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(hostFile, "w") + for host in hostEntryList: + fp.write("%s\t%s\n" % (host.keys()[0], " ".join(host.values()[0]))) + fp.close() + if hostFile == fileName: + return True + except IOError: + log("failed to write %s file" % hostFile) + return False + if runCommandFG("mv -f %s /etc/hosts" % hostFile, root=True) != 0: + log("failed to rename file %s to /etc/hosts" % hostFile) + return False + return True + + +def readResolvConfFile(fileName=None, includeLocalHost=False): + nameServerList = [] + domain = None + searchDomain = None + if not fileName: + fileName = Globals.RESOLV_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].strip().split() + if len(tokens) < 2: + continue + if tokens[0].upper() == "NAMESERVER": + if includeLocalHost == False and tokens[1] == "127.0.0.1": + continue + nameServerList.append(tokens[1]) + continue + if tokens[0].upper() == "DOMAIN": + domain = tokens[1:] + continue + if tokens[0].upper() == "SEARCH": + searchDomain = tokens[1:] + continue + return nameServerList, domain, searchDomain + except IOError: + log("failed to read %s file" % fileName) + return None, None, None + + +def writeResolvConfFile(nameServerList, domain, searchDomain, fileName=None, appendLocalHost=True): + if fileName: + resolvConfFile = fileName + else: + resolvConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(resolvConfFile, "w") + if appendLocalHost: + fp.write("nameserver 127.0.0.1\n") + for nameServer in nameServerList: + fp.write("nameserver %s\n" % nameServer) + if domain: + fp.write("domain %s\n" % " ".join(domain)) + if searchDomain: + fp.write("search %s\n" % " ".join(searchDomain)) + fp.close() + if resolvConfFile == fileName: + return True + except IOError: + log("failed to write %s file" % resolvConfFile) + return False + if runCommandFG("mv -f %s %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE), root=True) != 0: + log("failed to rename file %s to %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE)) + return False + return True + + +def readIfcfgConfFile(deviceName, root=""): + conf = {} + fileName = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + try: + for line in open(fileName): + tokens = line.split("#")[0].split("=") + if len(tokens) != 2: + continue + conf[tokens[0].strip().lower()] = tokens[1].strip() + return conf + except IOError: + log("failed to read %s file" % fileName) + return None + + +def writeIfcfgConfFile(deviceName, conf, root="", deviceFile=None): + if not deviceFile: + deviceFile = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) + if root: + ifcfgConfFile = deviceFile + else: + ifcfgConfFile = tempfile.mktemp(prefix="GSPSA") + try: + fp = open(ifcfgConfFile, "w") + for key in conf.keys(): + if key == "description": + fp.write("#%s=%s\n" % (key.upper(), conf[key])) + continue + if key in ['link', 'mode']: + continue + if conf["device"].startswith("bond") and key in ['hwaddr', 'master', 'slave']: + continue + if key == "slave" and conf['master']: + fp.write("SLAVE=yes\n") + continue + if key == "onboot": + if conf[key] == True: + fp.write("ONBOOT=yes\n") + elif isString(conf[key]) and conf[key].upper() == "YES": + fp.write("ONBOOT=yes\n") + else: + fp.write("ONBOOT=no\n") + continue + if not conf[key]: + continue + fp.write("%s=%s\n" % (key.upper(), conf[key])) + fp.close() + if ifcfgConfFile == deviceFile: + return True + except IOError: + log("failed to write %s file" % ifcfgConfFile) + return False + if runCommandFG("mv -f %s %s" % (ifcfgConfFile, deviceFile), root=True) != 0: + log("failed to rename file %s to %s" % (ifcfgConfFile, deviceFile)) + return False + return True + +def getNetDeviceDetail(deviceName): + deviceDetail = {} + deviceDetail['Name'] = deviceName + rv = runCommandFG("ifconfig %s" % deviceName, stdout=True, root=True) + if rv["Status"] != 0: + return False + for line in rv["Stdout"].split(): + tokens = line.strip().split(":") + if tokens[0].upper() == "ENCAP": + deviceDetail['Model'] = tokens[1].strip().upper() + break + + for line in rv["Stdout"].split("\n"): + if line.strip().startswith("inet addr:"): + tokens = line.strip().split(":") + if tokens[0].upper() == "INET ADDR": + try: + deviceDetail['Ip'] = tokens[1].strip().split()[0] + deviceDetail['Mask'] = tokens[-1].strip() + except IndexError: + pass + break + return deviceDetail + +def getNetDeviceGateway(deviceName): + rv = runCommand("route -n", output=True, root=True) + if rv["Status"] != 0: + return None + if not rv["Stdout"]: + return None + lines = [line for line in rv["Stdout"].split("\n") if line.find("UG") != -1 and line.find(deviceName)] + if not lines: + return None + line = lines[-1].split() + if line and len(line) > 1: + return line[1] + return None + +def getNetSpeed(deviceName): + rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) + if rv["Status"] != 0: + return False + for line in rv["Stdout"].split("\n"): + tokens = line.strip().split(":") + if tokens[0].upper() == "SPEED": + return tokens[1].strip().upper().split("MB")[0] + return None + +def getLinkStatus(deviceName): + return True + ## ethtool takes very long time to respond. So its disabled now + rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) + if rv["Status"] != 0: + return False + for line in rv["Stdout"].split("\n"): + tokens = line.strip().split(":") + if tokens[0].upper() == "LINK DETECTED": + if tokens[1].strip().upper() == "YES": + return True + else: + return False + return False + + +def getBondMode(deviceName, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + try: + for line in open(fileName): + tokens = line.split("#")[0].split() + if len(tokens) < 4: + continue + if tokens[0].upper() == "OPTIONS" and tokens[1] == deviceName: + if tokens[2].startswith("mode="): + return tokens[2].split("=")[1] + if tokens[3].startswith("mode="): + return tokens[3].split("=")[1] + if tokens[4].startswith("mode="): + return tokens[4].split("=")[1] + if tokens[5].startswith("mode="): + return tokens[5].split("=")[1] + return None + except IOError: + log("failed to read %s file" % fileName) + return None + + +def setBondMode(deviceName, mode, fileName=None): + if not fileName: + fileName = Globals.MODPROBE_CONF_FILE + tempFileName = getTempFileName() + try: + fp = open(tempFileName, "w") + lines = open(fileName).readlines() + except IOError: + log("unable to open file %s" % Globals.MODPROBE_CONF_FILE) + return False + for line in lines: + tokens = line.split() + if len(tokens) > 1 and "OPTIONS" == tokens[0].upper() and "BOND" in tokens[1].upper() and deviceName == tokens[1]: + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + deviceName = None + continue + fp.write(line) + if deviceName: + fp.write("alias %s bonding\n" % deviceName) + fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) + fp.close() + if runCommandFG(["mv", "-f", tempFileName, fileName], root=True) != 0: + log("unable to move file from %s to %s" % (tempFileName, fileName)) + return False + return True + +def getNetDeviceList(root=""): + netDeviceList = [] + for deviceName in os.listdir("/sys/class/net/"): + netDevice = {} + netDevice["device"] = None + netDevice["description"] = None + netDevice["hwaddr"] = None + netDevice["type"] = None + netDevice["onboot"] = None + netDevice["bootproto"] = None + netDevice["gateway"] = None + netDevice["peerdns"] = None + netDevice["autodns"] = None + netDevice["dns1"] = None + netDevice["dns2"] = None + netDevice["dns3"] = None + netDevice["master"] = None + netDevice["slave"] = None + netDevice["nmcontrolled"] = None + netDevice["link"] = None + netDevice["mode"] = None + + #netDevice["device"] = device.Name + netDevice["device"] = deviceName + #netDevice["description"] = device.Description + netDevice["description"] = deviceName + #netDevice["type"] = device.Type + netDevice["type"] = None + netDevice["link"] = getLinkStatus(deviceName) + netDevice["mode"] = getBondMode(deviceName, root + Globals.MODPROBE_CONF_FILE) + deviceDetail = getNetDeviceDetail(deviceName) + if deviceDetail.has_key('Model'): + netDevice["model"] = deviceDetail['Model'] + else: + netDevice["model"] = None + if deviceDetail.has_key('Ip'): + netDevice["ipaddr"] = deviceDetail['Ip'] + else: + netDevice["ipaddr"] = None + if deviceDetail.has_key('Mask'): + netDevice["netmask"] = deviceDetail['Mask'] + else: + netDevice["netmask"] = None + netDevice["speed"] = getNetSpeed(deviceName) + try: + netDevice["hwaddr"] = open("/sys/class/net/%s/address" % deviceName).read().strip() + except IOError: + pass + + netDeviceList.append(netDevice) + + conf = readIfcfgConfFile(deviceName, root) + if not conf: + continue + try: + netDevice["onboot"] = conf["onboot"] + except KeyError: + pass + try: + netDevice["bootproto"] = conf["bootproto"] + except KeyError: + pass + if conf.has_key("ipaddr") and conf["ipaddr"]: + netDevice["ipaddr"] = conf["ipaddr"] + try: + netDevice["netmask"] = conf["netmask"] + except KeyError: + pass + if conf.has_key("gateway") and conf["gateway"]: + netDevice["gateway"] = conf["gateway"] + else: + netDevice["gateway"] = getNetDeviceGateway(deviceName) + try: + netDevice["peerdns"] = conf["peerdns"] + except KeyError: + pass + try: + netDevice["autodns"] = conf["autodns"] + except KeyError: + pass + try: + netDevice["dns1"] = conf["dns1"] + except KeyError: + pass + try: + netDevice["dns2"] = conf["dns2"] + except KeyError: + pass + try: + netDevice["dns3"] = conf["dns3"] + except KeyError: + pass + try: + netDevice["master"] = conf["master"] + except KeyError: + pass + try: + netDevice["slave"] = conf["slave"] + except KeyError: + pass + try: + netDevice["nmcontrolled"] = conf["nmcontrolled"] + except KeyError: + pass + + return netDeviceList + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + + ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] + ## for deviceName in bondDevices: + ## if deviceName in linkedBondList: + ## if deviceName in sysConfigDeviceList: + ## deviceList[deviceName] = sysConfigDeviceList[deviceName] + ## else: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + ## continue + ## if len(ethDevices) > 2: + ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} + + +def configureDhcpServer(serverIpAddress, dhcpIpAddress): + tmpDhcpConfFile = tempfile.mktemp(prefix="GSPSA") + + serverPortString = "68" + try: + for arg in open("/proc/cmdline").read().strip().split(): + token = arg.split("=") + if token[0] == "dhcp": + serverPortString = token[1] + break + except IOError: + log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") + try: + serverPort = int(serverPortString) + except ValueError: + log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) + serverPort = 68 + + try: + fp = open(tmpDhcpConfFile, "w") + fp.write("bind-interfaces\n") + fp.write("except-interface=lo\n") + fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) + fp.write("dhcp-lease-max=1\n") + fp.write("dhcp-alternate-port=%s\n" % serverPort) + fp.write("dhcp-leasefile=%s\n" % Globals.DNSMASQ_LEASE_FILE) + #fp.write("server=%s\n" % serverIpAddress) + #fp.write("dhcp-script=/usr/sbin/server-info\n") + fp.close() + except IOError: + log(syslog.LOG_ERR, "unable to write dnsmasq dhcp configuration %s" % tmpDhcpConfFile) + return False + if runCommandFG("mv -f %s %s" % (tmpDhcpConfFile, Globals.DNSMASQ_DHCP_CONF_FILE), root=True) != 0: + log(syslog.LOG_ERR, "unable to copy dnsmasq dhcp configuration to %s" % Globals.DNSMASQ_DHCP_CONF_FILE) + return False + return True + + +def isDhcpServer(): + return os.path.exists(Globals.DNSMASQ_DHCP_CONF_FILE) + + +def getDhcpServerStatus(): + if runCommandFG("service dnsmasq status", root=True) == 0: + return True + return False + + +def startDhcpServer(): + if runCommandFG("service dnsmasq start", root=True) == 0: + return True + return False + + +def stopDhcpServer(): + if runCommandFG("service dnsmasq stop", root=True) == 0: + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return True + return False + + +def restartDhcpServer(): + stopDhcpServer() + runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) + return startDhcpServer() + + +def reloadDhcpServer(): + if runCommandFG("service dnsmasq reload", root=True) == 0: + return True + return False diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py b/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Protocol.py @@ -0,0 +1,438 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc.strip() + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTextNode(self, text): + if not self._domObj: + return False + if not text: + return False + return self._domObj.createTextNode(str(text)) + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def getAttribute(self, attributeName): + if not attributeName: + return None + try: + return self.getElementsByTagName("command")[0].getAttribute(attributeName) + except IndexError: + return False + + def setAttribute(self, attributeName, attributeValue): + if not (attributeName and attributeValue): + return None + try: + return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue) + except IndexError: + return False + + def getRequestCommand(self): + return self.getAttribute("request") + + def getResponseCommand(self): + return self.getAttribute("response") + + def getResponseCode(self): + return self.getAttribute("response-code") + + def getMessageId(self): + return self.getAttribute("id") + + def getVersion(self): + return self.getAttribute("version") + + def getRequestAction(self): + return self.getAttribute("action") + + def setVersion(self, value): + return self.setAttribute("version", value) + + def setRequestAction(self, value): + return self.setAttribute("action", value) + + def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + commandTag = self._domObj.createElement("command") + commandTag.setAttribute("response", command) + commandTag.setAttribute("response-code", responseCode) + commandTag.setAttribute("id", id) + commandTag.setAttribute("version", version) + return commandTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + +class ResponseXml(XDOM): + _commandTag = None + def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + XDOM.__init__(self) + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + + def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + return True + return False + + def append(self, tagName, tagValue=None): + if not self._commandTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._commandTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._commandTag: + return False + self._commandTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._commandTag: + return False + if not tagRoute: + return False + + parentTagE = self._commandTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def appendTagRouteOld(self, tagRoute, value=None): + if not tagRoute: + return False + if not self._commandTag: + return False + + tmpTagRoute = "" + previousTagE = self._commandTag + tagE = None + for tagName in tagRoute.split("."): + if not tmpTagRoute: + tagE = self.getElementsByTagRoute("command." + tagName) + else: + tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName) + if not tagE: + break + if len(tagE) != 1: + return False + previousTagE = tagE[0] + if not tmpTagRoute: + tmpTagRoute = tagName + else: + tmpTagRoute = tmpTagRoute + "." + tagName + + if tmpTagRoute == tagRoute: + return False + newTagRoute = tagRoute[len(tmpTagRoute):] + if newTagRoute[0] == '.': + newTagRoute = newTagRoute[1:] + + if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE: + return False + previousTagE.appendChild(self.createTagRoute(newTagRoute, value)) + return True +##--end of ResponseXml + +def test(): + #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume") + requestStr = ''' + +movies1 +cluster mirror +512000 +zresearch +192.168.20.* +192.168.30.* + +no + + +no + + +no + + +''' + + requestXml = RequestXml(requestStr) + print requestXml.getAttribute("") + +def test1(): + rs = ResponseXml("create-volume", "OK", "xyz") + rs.appendTagRoute("volume.detail.name", "music") + print rs.toprettyxml() + rs.append("volume", "data") + print rs.toprettyxml() + rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1") + print rs.toprettyxml() + print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::") + print rs.toprettyxml() + + print rs.getTextByTagRoute("command.volume.detail") + +def test2(): + rs = ResponseXml("download-volume-logs", "OK", "xyz") + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE1")) + te.appendChild(rs.createTag("description", "my device one")) + rs.appendTag(te) + + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE2")) + te.appendChild(rs.createTag("description", "my device two")) + rs.appendTag(te) + print rs.toprettyxml() + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py new file mode 100644 index 00000000..1ad0deee --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/RRDUtils.py @@ -0,0 +1,72 @@ +import rrdtool +import os +from socket import gethostname +from itertools import groupby + +class RRD: + def __init__ (self): + self.COLORS = [0xff7777, 0x7777ff, 0x55ff55, 0xffcc77, 0xff77ff, 0x77ffff,0xffff77, 0x55aaff] + self.HOST = gethostname() + self.DIR = "/var/lib/collectd" + + def fade_component(self, component): + return ((component + 255 * 5) / 6) + + def fade_color(self, color): + r = 0; + for i in [0,1,2]: + shft = (i * 8) + component = ((color >> shft) & 255) + r |= (self.fade_component(component) << shft) + return r + + def generate_pngs(self): + + rrdlist = os.popen ("find %s -type f -name '*.rrd'" % self.DIR) + + for rrd in rrdlist: + self.dss = [] + self.defs = "" + + rrdinfo = rrdtool.info(rrd.strip()) + + for key in rrdinfo.keys(): + if key.split('[')[0] == 'ds': + self.dss.append(key.split('[')[1].split(']')[0]) + self.dss.sort() + + self.dss = [a for a,b in groupby(self.dss)] + + for ds in self.dss: + self.defs = self.defs + " DEF:%s_avg=%s:%s:AVERAGE " % (ds, rrd.strip(), ds) + self.defs = self.defs + " DEF:%s_max=%s:%s:MAX " % (ds, rrd.strip(), ds) + + j = 0 + for ds in self.dss: + color = self.COLORS[j % len(self.COLORS)] + j = j + 1 + faded_color = self.fade_color(color) + self.defs = self.defs + " AREA:%s_max#%06x " % (ds, faded_color) + + j = 0 + for ds in self.dss: + color = self.COLORS[j % len(self.COLORS)] + j = j + 1 + self.defs = self.defs + " LINE2:%s_avg#%06x:%s " % (ds, color, ds) + self.defs = self.defs + " GPRINT:%s_avg:AVERAGE:%%5.1lf%%sAvg " % ds + self.defs = self.defs + " GPRINT:%s_max:MAX:%%5.1lf%%sMax " % ds + + for span in ['1hour', '1day', '1week', '1month']: + os.system ("mkdir -p %s/%s" % (self.DIR, self.HOST)) + image = os.path.dirname(rrd.strip()) + "-" + span + ".png" + cmd = "rrdtool graph " + image + " -t \"%s %s\"" % (os.path.dirname(rrd.strip()), span) + " --imgformat PNG --width 600 --height 100 --start now-" + span + " --end now --interlaced " + self.defs + " >/dev/null 2>&1" + os.system(cmd) + + +def main (): + + rrd = RRD () + rrd.generate_pngs () + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py new file mode 100644 index 00000000..1fec994c --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/ServerUtils.py @@ -0,0 +1,308 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import re +import subprocess +import glob +import Globals +from Protocol import * +from Utils import * + +def isValidServer(serverName): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + if serverName == profile.DNS.Hostname: + return True + return False + +def getHostname(): + for profile in getProfileList(): + if profile.ProfileName == "default" and profile.Active: + return profile.DNS.Hostname + return None + +def getDomainName(): + try: + domainName = open(Globals.DOMAINNAME_FILE).read() + except IOError: + return None + return domainName.split()[0] + +def replaceServerIp(fileName, findWhat, replaceWith): + try: + data = open(fileName).read() + fp = open(fileName, "w") + fp.write(re.sub(findWhat, replaceWith, data)) + fp.close() + return True + except IOError: + return False + except ValueError: + return False + except OSError: + return False + +def serverName2IpAddress(serverName): + command = "dig %s | grep '^%s'" % (serverName, serverName) + ps = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stdin=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True) + ipAddress = serverName + if ps.wait() == 0: + output = ps.communicate() + ipAddress = output[0].split()[-1] + return ipAddress + +def getInstallerIp(): + if not os.path.exists(Globals.INSTALLER_INFO_FILE): + return None + try: + for line in open(Globals.INSTALLER_INFO_FILE): + tokens = line.split("=") + if tokens[0] == "IP-ADDRESS": + return tokens[1].split(",")[0].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def setInstallerIp(installerIp): + try: + open(Globals.INSTALLER_INFO_FILE, "w").write("IP-ADDRESS=%s\n" % installerIp) + return True + except IOError: + log(syslog.LOG_ERR, "unable to create %s file" % Globals.INSTALLER_INFO_FILE) + return False + +def getCurrentServerName(): + try: + for line in open(Globals.SYSCONFIG_NETWORK_FILE): + tokens = line.split("=") + if tokens[0] == "HOSTNAME": + return tokens[1].strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.SYSCONFIG_NETWORK_FILE) + return False + +def getLastAccessedNetwork(serverName): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + return open(lastAccessedNetworkFile).read().strip() + except IOError: + log(syslog.LOG_ERR, "failed to read last accessed network file %s" % lastAccessedNetworkFile) + pass + return False + +def setLastAccessedNetwork(serverName, ipAddress): + lastAccessedNetworkFile = ("/%s/servers/%s/%s" % + (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) + try: + open(lastAccessedNetworkFile, "w").write(ipAddress.strip() + "\n") + except IOError: + log(syslog.LOG_ERR, "failed to write last accessed network file %s" % lastAccessedNetworkFile) + return False + return True + +def getServerIpList(serverName, preferredNetworkOnly=False): + networkXmlFile = ("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + configDom = XDOM() + if not configDom.parseFile(networkXmlFile): + log(syslog.LOG_ERR, "failed to read %s file" % networkXmlFile) + return None + preferredNetwork = configDom.getTextByTagRoute("preferred-network") + ipList = [] + interfaceDom = XDOM() + for tagE in configDom.getElementsByTagName("interface"): + interfaceDom.setDomObj(tagE) + deviceName = interfaceDom.getTextByTagRoute("device") + hostIp = interfaceDom.getTextByTagRoute("ipaddr") + if not hostIp: + continue + if preferredNetworkOnly: + if preferredNetwork.upper() == "ANY" or preferredNetwork.upper() == deviceName.upper(): + ipList.append(hostIp) + else: + ipList.append(hostIp) + if preferredNetworkOnly: + lastAccessedNetworkIp = getLastAccessedNetwork(serverName) + if lastAccessedNetworkIp in ipList: + ipList.remove(lastAccessedNetworkIp) + ipList = [lastAccessedNetworkIp] + ipList + return ipList + +def getServerPreferredIpList(serverName): + return getServerIpList(serverName, True) + +def getExecuteServerList(serverList): + executeServerList = {} + for serverName in serverList: + if serverName == Globals.INSTALLER_SERVER_NAME: + installerIp = getInstallerIp() + if installerIp: + executeServerList[serverName] = [installerIp] + continue + executeServerList[serverName] = getServerPreferredIpList(serverName) + return executeServerList + +def getAllServerList(): + serverList = [] + for filePath in glob.glob("%s/servers/*" % Globals.GLUSTER_CONF_DIR): + if os.path.isdir(filePath): + serverList.append(os.path.basename(filePath)) + try: + serverList.remove(Globals.INSTALLER_SERVER_NAME) + except ValueError: + pass + return serverList + +def getServerNetworkConfigFromLocalFile(serverName): + configDom = XDOM() + configDom.parseFile("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) + return configDom + +def updateServerNetworkConfigXmlFile(serverName, serverNetworkDom): + configDom = XDOM() + serverTag = serverNetworkDom.getElementsByTagRoute("server")[0] + configDom.setDomObj(serverTag) + if not configDom.writexml("%s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): + log("Faild to write xml file %s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) + +def compareServerNetworkDom(serverNetworkDomA, serverNetworkDomB, requestFlag=True): + command = "command.server." + if not requestFlag: + command = "" + sourceServer = {} + tagText = serverNetworkDomA.getTextByTagRoute("name") + if not tagText: + taxText = None + sourceServer["name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("domain-name") + if not tagText: + tagText = None + sourceServer["domain-name"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("search-domain") + if not tagText: + tagText = None + sourceServer["search-domain"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns1") + if not tagText: + tagText = None + sourceServer["dns1"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns2") + if not tagText: + tagText = None + sourceServer["dns2"] = tagText + tagText = serverNetworkDomA.getTextByTagRoute("dns3") + if not tagText: + tagText = None + sourceServer["dns3"] = tagText + for tagE in serverNetworkDomA.getElementsByTagRoute("interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + sourceServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + sourceServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + sourceServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + sourceServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + sourceServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + sourceServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + sourceServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + sourceServerList["gateway"] = tagText + sourceServer[interfaceDom.getTextByTagRoute("device")] = sourceServerList + objServer = {} + tagText = serverNetworkDomB.getTextByTagRoute(command + "name") + if not tagText: + taxText = None + objServer["name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "domain-name") + if not tagText: + tagText = None + objServer["domain-name"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "search-domain") + if not tagText: + tagText = None + objServer["search-domain"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns1") + if not tagText: + tagText = None + objServer["dns1"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns2") + if not tagText: + tagText = None + objServer["dns2"] = tagText + tagText = serverNetworkDomB.getTextByTagRoute(command + "dns3") + if not tagText: + tagText = None + objServer["dns3"] = tagText + for tagE in serverNetworkDomB.getElementsByTagRoute(command + "interface"): + interfaceDom = XDOM() + interfaceDom.setDomObj(tagE) + objServerList = {} + tagText = interfaceDom.getTextByTagRoute("description") + if not tagText: + tagText = None + objServerList["description"] = tagText + tagText = interfaceDom.getTextByTagRoute("hwaddr") + if not tagText: + tagText = None + objServerList["hwaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("onboot") + if not tagText: + tagText = None + objServerList["onboot"] = tagText + tagText = interfaceDom.getTextByTagRoute("bootproto") + if not tagText: + tagText = None + objServerList["bootproto"] = tagText + tagText = interfaceDom.getTextByTagRoute("ipaddr") + if not tagText: + tagText = None + objServerList["ipaddr"] = tagText + tagText = interfaceDom.getTextByTagRoute("netmask") + if not tagText: + tagText = None + objServerList["netmask"] = tagText + tagText = interfaceDom.getTextByTagRoute("gateway") + if not tagText: + tagText = None + objServerList["gateway"] = tagText + objServer[interfaceDom.getTextByTagRoute("device")] = objServerList + return sourceServer == objServer diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Utils.py b/src/com.gluster.storage.management.gateway.scripts/src/Utils.py new file mode 100644 index 00000000..3408c14a --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/Utils.py @@ -0,0 +1,1059 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import os +import re +import socket +import struct +import syslog +import subprocess +#import spwd +import time +#import uuid +import tempfile +import grp +import pwd +import inspect +from datetime import datetime +import urllib + +import Globals +import Protocol + +RUN_COMMAND_ERROR = -1024 +LOG_SYSLOG = 1 +SYSLOG_REQUIRED = False +LOG_FILE_NAME = None +LOG_FILE_OBJ = None + + +def _getLogCode(priority): + if syslog.LOG_EMERG == priority: + return "M" + elif syslog.LOG_ALERT == priority: + return "A" + elif syslog.LOG_CRIT == priority: + return "C" + elif syslog.LOG_ERR == priority: + return "E" + elif syslog.LOG_WARNING == priority: + return "W" + elif syslog.LOG_NOTICE == priority: + return "N" + elif syslog.LOG_INFO == priority: + return "I" + elif syslog.LOG_DEBUG == priority: + return "D" + else: # UNKNOWN + return "X" + + +def setLogFile(fileName): + global LOG_FILE_NAME + + if fileName: + LOG_FILE_NAME = fileName + return True + return False + + +def closeLog(): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if SYSLOG_REQUIRED: + syslog.closelog() + SYSLOG_REQUIRED = False + return True + + if LOG_FILE_OBJ: + try: + LOG_FILE_OBJ.close() + LOG_FILE_OBJ = None + except IOError, e: + sys.stderr.write("Failed to close file: %s\n" % e) + return False + return True + + +def openLog(fileName=None): + global LOG_FILE_NAME + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if fileName == LOG_SYSLOG: + syslog.openlog(os.path.basename(sys.argv[0])) + SYSLOG_REQUIRED = True + return True + + if fileName: + LOG_FILE_NAME = fileName + + if not LOG_FILE_NAME: + return False + + closeLog() + + try: + LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") + except IOError, e: + sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) + return False + return True + +def record(priority, message=None): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + stack = inspect.stack()[1] + if stack[3] == "": + prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3]) + else: + prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3]) + + if type(priority) == type("") or type(priority) == type(u""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + + if SYSLOG_REQUIRED: + syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage)) + return + + fp = sys.stderr + if LOG_FILE_OBJ: + fp = LOG_FILE_OBJ + + fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage)) + if logMessage[-1] != '\n': + fp.write("\n") + fp.flush() + return + + +def trace(message): + if message: + log(syslog.LOG_DEBUG, message) + + +def isString(value): + return (type(value) == type("") or type(value) == type(u"")) + + +def getTempFileName(): + filedesc, filename = tempfile.mkstemp(prefix="GSP_") + os.close(filedesc) + return filename + + +def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, + shell=False, root=None): + log("runCommandBG(): Trying to execute command [%s]" % command) + + if shell: + if not isString(command): + return None + else: + if isString(command): + command = command.split() + + if root == True: + if shell: + command = "sudo " + command + else: + command = ['sudo'] + command + elif isString(root): + if shell: + command = "sudo -u " + root + " " + command + else: + command = ['sudo', '-u', root] + command + + if not stdinFileObj: + stdinFileObj=subprocess.PIPE + if not stdoutFileObj: + stdoutFileObj=subprocess.PIPE + if not stderrFileObj: + stderrFileObj=subprocess.PIPE + + try: + process = subprocess.Popen(command, + bufsize=-1, + stdin=stdinFileObj, + stdout=stdoutFileObj, + stderr=stderrFileObj, + shell=shell) + return process + except OSError, e: + log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) + return None + + +def runCommand(command, + input='', output=False, + shell=False, root=None): + rv = {} + rv["Status"] = RUN_COMMAND_ERROR + rv["Stdout"] = None + rv["Stderr"] = None + + try: + stdinFileName = getTempFileName() + stdinFileObj = open(stdinFileName, "w") + stdinFileObj.write(input) + stdinFileObj.close() + stdinFileObj = open(stdinFileName, "r") + + stdoutFileName = getTempFileName() + stdoutFileObj = open(stdoutFileName, "w") + + stderrFileName = getTempFileName() + stderrFileObj = open(stderrFileName, "w") + except IOError, e: + log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) + if output: + return rv + return rv["Status"] + + stdoutContent = None + stderrContent = None + + process = runCommandBG(command, + stdinFileObj=stdinFileObj, + stdoutFileObj=stdoutFileObj, + stderrFileObj=stderrFileObj, + shell=shell, root=root) + if process: + rv['Status'] = process.wait() + rv['Stdout'] = open(stdoutFileName).read() + rv['Stderr'] = open(stderrFileName).read() + + os.remove(stdinFileName) + os.remove(stdoutFileName) + os.remove(stderrFileName) + + log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) + + if output: + return rv + return rv["Status"] + + +def runCommandFG(command, stdout=False, stderr=False, + shell=False, root=None): + if stdout or stderr: + output = True + else: + output = False + return runCommand(command, output=output, shell=shell, root=root) + + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + + +def computeHostName(hostName): + if not hostName: + return False + + hostPrefix = "" + for i in range(len(hostName), 0, -1): + pos = i - 1 + if hostName[pos].isdigit(): + continue + break + hostPrefix = hostName[:pos+1] + try: + hostIndex = int(hostName[pos+1:]) + except ValueError: + hostIndex = 0 + # TODO: Check the availablity of the (server) name + return "%s%s" % (hostPrefix, hostIndex + 1) + + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + + +def getDownloadStatus(fileName): + try: + lines = [line for line in open(fileName) + if "saved" in line or "%" in line] + except IOError: + return 0 + if not lines: + return 0 + if "saved" in lines[-1]: + return 100 + return lines[-1].split("%")[0].split()[-1] + + +def getMeminfo(): + """-> dict of data from meminfo (str:int). + Values are in kilobytes. + """ + import re + re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB' ) + result = {} + for line in open('/proc/meminfo'): + match = re_parser.match(line) + if not match: + continue # skip lines that don't parse + key, value = match.groups(['key', 'value']) + result[key] = int(value) + result['MemUsed'] = (result['MemTotal'] - result['MemFree']) + return result + + +def getCpuUsage(): + """-> dict of cpuid : (usertime, nicetime, systemtime, idletime) + cpuid "cpu" means the total for all CPUs. + cpuid "cpuN" means the value for CPU N. + """ + wanted_records = [line for line in open('/proc/stat') if + line.startswith('cpu')] + result = {} + for cpuline in wanted_records: + fields = cpuline.split()[:5] + data = map(int, fields[1:]) + result[fields[0]] = tuple(data) + return result + +def _getCpuStatList(): + try: + fp = open("/proc/stat") + cpuStatList = map(float, fp.readline().split()[1:]) + fp.close() + return cpuStatList + except IOError, e: + Utils.log("Failed to open /proc/stat: %s" % str(e)) + return None + +def getCpuUsageAvg(): + st1 = _getCpuStatList() + time.sleep(2) + st2 = _getCpuStatList() + if not (st1 and st2): + return None + delta = [st2[i] - st1[i] for i in range(len(st1))] + cpuPercent = sum(delta[:3]) / delta[3] * 100.0 + return str('%.4f' % cpuPercent) + +def getLoadavg(): + try: + loadavgstr = open('/proc/loadavg', 'r').readline().strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "failed to find cpu load") + return None + + data = map(float, loadavgstr.split()[1:]) + # returns 1 minute load average + return data[0] + + +def getInfinibandPortStatus(): + + """ Check for availability of infiniband port + and return which port is active in a key pair value + """ + + # Check for existence of infiniband ports + value = os.popen ("ls /sys/class/infiniband").readline().strip() + + if not value: + return None + + portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split() + + portkeys = {} + + for port in portlist: + value = os.popen ("cat %s/state" % + port.strip()).readline().split(':')[1].strip() + portkeys[port.strip()] = value + + return portkeys + + +def getServerCount(): + try: + return int(open(Globals.SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE) + return 1 + + +def setServerCount(count): + try: + open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.SERVER_COUNT_FILE) + return False + + +def getInstalledServerCount(): + try: + return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + + +def setInstalledServerCount(count): + try: + open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return False + + +def getLastInstalledServerIpList(): + ipList = {} + networkDom = Protocol.XDOM() + if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE): + log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE) + for tagE in networkDom.getElementsByTagRoute("server.interface"): + interfaceDom = Protocol.XDOM() + interfaceDom.setDomObj(tagE) + ipAddress = interfaceDom.getTextByTagRoute("ipaddr") + if ipAddress: + ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress + return ipList + + +def getFreeIpAddress(device=None): + serverCount = getServerCount() + installedServerCount = getInstalledServerCount() + if serverCount == installedServerCount: + return None + + availableServerCount = serverCount - installedServerCount + ipList = getLastInstalledServerIpList() + + if not ipList: + return None + + if device: + if device not in ipList.keys(): + return None + deviceIpAddress = ipList[device] + else: + deviceIpAddress = ipList.values()[0] + ipNumber = IP2Number(deviceIpAddress) + + for i in range((ipNumber + availableServerCount), ipNumber, -1): + ipAddress = Number2IP(i) + if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0: + return ipAddress + return None + + +def getPasswordHash(userName): + try: + #return spwd.getspnam(userName).sp_pwd + return "Not implimented" + except KeyError: + return None + + +def getTransactionKey(): + try: + tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',') + except IOError: + return None, None + return tokens + + +def generateSignature(): + #return str(uuid.uuid4()) + ('--%f' % time.time()) + return ('--%f' % time.time()) + + +def getSignature(): + try: + return open(Globals.SIGNATURE_FILE).read().strip() + except IOError: + log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE) + return False + + +def storeSignature(signature, fileName=Globals.SIGNATURE_FILE): + try: + open(fileName, "w").write(signature + "\n") + except IOError: + log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName)) + return False + return True + + +def isUserExist(userName): + try: + grp.getgrnam(userName).gr_gid + return True + except KeyError: + pass + try: + pwd.getpwnam(userName).pw_uid + return True + except KeyError: + pass + return False + + +def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE): + userInfo = {} + userInfo["UserId"] = None + userInfo["Password"] = None + try: + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "GSN_ID": + userInfo["UserId"] = v + if k.upper() == "GSN_PASSWORD": + userInfo["Password"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return userInfo + + +def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE): + try: + fp = open(fileName, "w") + fp.write("GSN_ID=%s\n" % userInfo["UserId"]) + fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"]) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE): + versionInfo = {} + versionInfo["Version"] = None + versionInfo["Update"] = None + try: + lines = open(Globals.GLUSTER_VERSION_FILE).readlines() + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "VERSION": + versionInfo["Version"] = v + if k.upper() == "UPDATE": + versionInfo["Update"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return versionInfo + + +def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE): + if isString(versionInfo): + tokens = versionInfo.strip().split(".") + if len(tokens) < 2: + log("Invalid version format %s. Expecting .." % versionInfo) + return False + version = ".".join(tokens[:2]) + update = ".".join(tokens[2:]) + if not update: + update = "0" + else: + version = versionInfo["Version"] + update = versionInfo["Update"] + try: + fp = open(fileName, "w") + fp.write("VERSION=%s\n" % version) + fp.write("UPDATE=%s\n" % update) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getGlusterUpdateDom(serverVersion): + errorMessage = "" + updateInfoDom = None + try: + baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip() + except IOError, e: + log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e)) + errorMessage = "Failed to read update site file" + return updateInfoDom, errorMessage + + try: + url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE) + connection = urllib.urlopen(url) + if connection.getcode() != 200: + connection.close() + errorMessage = "Error received from server to open URL %s" % url + return updateInfoDom, errorMessage + updateInfoString = connection.read() + connection.close() + except IOError, e: + log("Failed to get update information from URL %s: %s" % (url, e)) + errorMessage = "Error getting update information" + return updateInfoDom, errorMessage + + updateInfoDom = Protocol.XDOM() + if not updateInfoDom.parseString(updateInfoString): + log("XML parse error on update information content [%s]" % updateInfoString) + errorMessage = "Parse error on update information" + updateInfoDom = None + return updateInfoDom, errorMessage + + +def removeFile(fileName, root=False): + if root: + if runCommand("rm %s" % fileName, root=True) == 0: + return True + return False + try: + os.remove(fileName) + return True + except OSError, e: + log("Failed to remove file %s: %s" % (fileName, e)) + return False + + +def isLiveMode(): + return os.path.exists(Globals.LIVE_MODE_FILE) + +def convertKbToMb(kb): + return kb / 1024.0 + + +def getIPIndex(indexFile): + try: + fp = open(indexFile) + line = fp.readline() + fp.close() + index = int(line) + except IOError: + index = 0 + except ValueError: + index = False + return index + +def setIPIndex(index, indexFile): + try: + fp = open(indexFile, "w") + fp.write(str(index)) + fp.close() + except IOError: + return False + return True + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + +def hasEntryFoundInFile(searchString, dnsEntryFileName): + try: + addServerEntryList = open(dnsEntryFileName).read().split() + except IOError: + return None + if searchString in addServerEntryList: + return True + return False + + +def computeIpAddress(ipAddress, startIp, endIp): + startIpNumber = IP2Number(startIp) + endIpNumber = IP2Number(endIp) + if not ipAddress: + return startIp + nextIpNumber = IP2Number(ipAddress) + while True: + nextIpNumber = nextIpNumber + 1 + ipAddress = Number2IP(nextIpNumber) + rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) + if type(rv) == type(True): + return False + if rv != 0: + break + + if nextIpNumber >= startIpNumber and nextIpNumber <= endIpNumber: + return ipAddress + + nextIpNumber = IP2Number(startIp) + while True: + ipAddress = Number2IP(nextIpNumber) + nextIpNumber = nextIpNumber + 1 + rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) + if type(rv) == type(True): + return False + if rv != 0: + break + + if IP2Number(ipAddress) >= startIpNumber and IP2Number(ipAddress) <= endIpNumber: + return ipAddress + return False + + +def setHostNameAndIp(hostName, ipAddress, lastAddServerDetailFile): + try: + fp = open(lastAddServerDetailFile, "w") + fp.write("HOSTNAME=" + hostName + "\n") + fp.write("IPADDRESS=" + ipAddress); + fp.close() + except IOError: + return False + return True + +def getPort(): + try: + fd = open(Globals.PORT_FILE, "r") + portString = fd.readline() + fd.close() + port = int(portString) + except IOError: + port = Globals.DEFAULT_PORT - 2 + except ValueError: + port = Globals.DEFAULT_PORT - 2 + return port + +def setPort(port): + try: + fd = open(Globals.PORT_FILE, "w") + fd.write(str(port)) + fd.close() + except IOError: + return False + return True + +def getServerAgentCredentials(): + try: + lines = open(Globals.SERVERAGENT_AUTH_FILE).readlines() + except IOError: + return None,None + + userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "AGENT_ID": + userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return userName, password + +def getGatewayAgentCredentials(): + try: + lines = open(Globals.GATEWAYAGENT_AUTH_FILE).readlines() + except IOError: + return None + + #userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + #if k.upper() == "AGENT_ID": + # userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return password + +def getWebAgentCredentials(): + try: + lines = open(Globals.WEBAGENT_AUTH_FILE).readlines() + except IOError: + return None,None + + userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "AGENT_ID": + userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return userName, password + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + +def getFreeIpAddress(): + startRange, endRange = getStoragePoolInfo() + if not (startRange and endRange): + return None + + startIpNumber = IP2Number(startRange) + endIpNumber = IP2Number(endRange) + + for ipNumber in range(endIpNumber, startIpNumber, -1): + rv = runCommandFG(["ping", "-qnc", "1", Number2IP(ipNumber)]) + if type(rv) == type(True): + return None + if rv != 0: + return Number2IP(ipNumber) + return None + +def getDhcpServerStatus(): + status = runCommandFG(["sudo", "service", "dnsmasq", " status"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def startDhcpServer(): + status = runCommandFG(["sudo", "service", "dnsmasq", " start"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def stopDhcpServer(): + status = runCommandFG(["sudo", "service", "dnsmasq", " stop"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def getStoragePoolInfo(): + startRange = None + endRange = None + try: + for line in open(Globals.GLUSTER_SERVER_POOL_FILE): + tokens = line.split("=") + if tokens[0] == "STARTRANGE": + startRange = tokens[1].strip() + if tokens[0] == "ENDRANGE": + endRange = tokens[1].strip() + except IOError: + log(syslog.LOG_ERR, "unable to read %s file" % Globals.GLUSTER_SERVER_POOL_FILE) + return startRange, endRange + +def configureDnsmasq(serverIpAddress, dhcpIpAddress): + dnsmasqConfFile = Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf" + serverPortString = "68" + try: + for arg in open("/proc/cmdline").read().strip().split(): + token = arg.split("=") + if token[0] == "dhcp": + serverPortString = token[1] + break + except IOError: + log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") + try: + serverPort = int(serverPortString) + except ValueError: + log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) + serverPort = 68 + + try: + fp = open(dnsmasqConfFile, "w") + fp.write("no-hosts\n") + #fp.write("addn-hosts=%s\n" % Globals.GLUSTER_DNS_ENTRIES) + fp.write("bind-interfaces\n") + fp.write("except-interface=lo\n") + fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) + fp.write("dhcp-lease-max=1\n") + #fp.write("dhcp-option=option:router,%s\n" % serverIp) + #fp.write("dhcp-option=option:ntp-server,%s\n" % serverIp) + fp.write("dhcp-alternate-port=%s\n" % serverPort) + fp.write("server=%s\n" % serverIpAddress) + fp.write("dhcp-script=/usr/sbin/server-info\n") + fp.close() + except IOError: + log(syslog.LOG_ERR, "unable to write dnsmasq configuration %s" % dnsmasqConfFile) + return False + status = runCommandFG(["sudo", "cp", "-f", Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf", Globals.DNSMASQ_CONF_FILE]) + if type(status) == type(True) or 0 != status: + log(syslog.LOG_ERR, "unable to copy dnsmasq configuration to " + Globals.DNSMASQ_CONF_FILE) + return False + return True + +def configureDhcpServer(serverIpAddress, dhcpIpAddress): + return configureDnsmasq(serverIpAddress, dhcpIpAddress) + +def log(priority, message=None): + if type(priority) == type(""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + if not logMessage: + return + #if Globals.DEBUG: + # sys.stderr.write(logMessage) + else: + syslog.syslog(logPriority, logMessage) + return + + +def stripEmptyLines(content): + ret = "" + for line in content.split("\n"): + if line.strip() != "": + ret += line + return ret + + +def getDeviceFormatStatusFile(device): + return "/var/tmp/format_%s.status" % device.replace('/', '_') + +def getDeviceFormatLockFile(device): + return "/var/lock/format_%s.lock" % device.replace('/', '_') + +def getDeviceFormatOutputFile(device): + return "/var/tmp/format_%s.out" % device.replace('/', '_') diff --git a/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py b/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py new file mode 100644 index 00000000..b1031ccc --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/VolumeUtils.py @@ -0,0 +1,612 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import glob +import tempfile +from operator import itemgetter +import Globals +from Protocol import * +from Utils import * +from DiskUtils import * +from ServerUtils import * +import GlusterdUtils as Glusterd + + +def isVolumeExist(volumeName): + volumeDom = XDOM() + return volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)) and \ + Glusterd.isVolumeExist(volumeName) + + +def getVolumeUuid(volumeName): + fileName = "%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName) + volumeDom = XDOM() + if not volumeDom.parseFile(fileName): + log("Failed to parse volume configuration file %s of %s" % (fileName, volumeName)) + return None + return volumeDom.getTextByTagRoute("uuid") + + +def readVolumeSmbConfFile(fileName=Globals.VOLUME_SMBCONF_FILE): + entryList = [] + try: + fp = open(fileName) + for line in fp: + tokens = line.split("#")[0].strip().split(";")[0].strip().split("=") + if len(tokens) != 2: + continue + if tokens[0].strip().upper() == "INCLUDE": + entryList.append(tokens[1].strip()) + fp.close() + except IOError, e: + log("Failed to open file %s: %s" % (fileName, str(e))) + return entryList + + +def writeVolumeSmbConfFile(entryList, fileName=Globals.VOLUME_SMBCONF_FILE): + try: + fp = open(fileName, "w") + for entry in entryList: + fp.write("include = %s\n" % entry) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, str(e))) + return False + + +def includeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE): + volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) + if not os.path.exists(volumeFile): + return False + entryList = readVolumeSmbConfFile(fileName) + if volumeFile in entryList: + return True + entryList.append(volumeFile) + return writeVolumeSmbConfFile(entryList, fileName) + + +def excludeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE): + volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) + if not os.path.exists(volumeFile): + return False + entryList = readVolumeSmbConfFile(fileName) + if volumeFile not in entryList: + return True + entryList.remove(volumeFile) + log("entryList = %s" % entryList) + return writeVolumeSmbConfFile(entryList, fileName) + + +def writeVolumeCifsConfiguration(volumeName, userList, adminUser=None): + volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) + try: + fp = open(volumeFile, "w") + fp.write("[%s]\n" % volumeName) + fp.write(" comment = %s volume served by Gluster\n" % volumeName) + fp.write(" path = %s/%s\n" % (Globals.CIFS_EXPORT_DIR, volumeName)) + fp.write(" guest ok = yes\n") + fp.write(" public = yes\n") + fp.write(" writable = yes\n") + if adminUser: + fp.write(" admin users = %s, %s\n" % (adminUser, ", ".join(userList))) + fp.write(" valid users = %s, %s\n" % (adminUser, ", ".join(userList))) + else: + fp.write(" admin users = %s\n" % (", ".join(userList))) + fp.write(" valid users = %s\n" % (", ".join(userList))) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (volumeFile, str(e))) + return False + + +def removeVolumeCifsConfiguration(volumeName): + volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) + try: + os.remove(volumeFile) + return True + except OSError, e: + log("Failed to remove file %s: %s" % (volumeFile, str(e))) + return False + + +def getVolumeListByPartitionName(partitionName): + volumeConfigFileList = glob.glob(Globals.VOLUME_CONF_DIR + "/*.xml") + if not volumeConfigFileList: + return None + + volumeList = [] + for volumeXmlFile in volumeConfigFileList: + volumeDom = XDOM() + volumeDom.parseFile(volumeXmlFile) + serverTopology = volumeDom.getElementsByTagRoute("volume.topology.group") + serverPartitionFound = False + for topology in serverTopology: + partitionDom = XDOM() + for partition in topology.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + if partitionDom.getTextByTagRoute("name") == partitionName: + serverPartitionFound = True + break + if serverPartitionFound: + volumeList.append(volumeDom.getElementsByTagRoute("volume")[0]) + break + return volumeList + + +def addServerPartitionConfig(inputDom, groupOrder, partitionTag): + if not(inputDom and groupOrder and partitionTag): + return False + groupDom = XDOM() + for group in inputDom.getElementsByTagRoute("topology.group"): + groupDom.setDomObj(group) + order = groupDom.getTextByTagRoute("order") + if order and int(order) == groupOrder: + group.appendChild(partitionTag) + return inputDom + return False + + +def removeServerPartitionConfig(inputDom, partitionName): + if not(inputDom and partitionName): + return False + for group in inputDom.getElementsByTagRoute("topology.group"): + partitionDom = XDOM() + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + if partitionDom.getTextByTagRoute("name") == partitionName: + group.removeChild(partition) + return inputDom + return False + + +def updateServerPartitionConfig(inputDom, partitionName, partitionTag): + if not(inputDom and partitionName and partitionTag): + return False + for group in inputDom.getElementsByTagRoute("topology.group"): + partitionDom = XDOM() + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + if partitionDom.getTextByTagRoute("name") == partitionName: + try: + group.replaceChild(partitionTag, partition) + return inputDom + except AttributeError: + return False + return False + + +def getServerPartitionConfigUuid(serverGroupList, serverPartition): + for group in serverGroupList: + if not group: + continue + partitionDom = XDOM() + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + partitionName = partition.getTextByTagName("name") + if not partitionName: + continue + if partitionName == serverPartition: + return partitionDom.getTextByTagName("uuid") + return False + + +def setServerPartitionConfigProperty(inputDom, partitionName, propertyDict): + if not(inputDom and partitionName and propertyDict): + return False + for group in inputDom.getElementsByTagRoute("topology.group"): + partitionDom = XDOM() + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + if partitionDom.getTextByTagRoute("name") == partitionName: + for part in propertyDict.keys(): + x = partition.getElementsByTagName(part) + if x: + x[0].childNodes[0].nodeValue = propertyDict[part] + return inputDom + return False + + +def getSortedServerPartitionConfigProperty(inputDom): + groupDict = {} + if not inputDom: + return None + groupDom = XDOM() + for group in inputDom.getElementsByTagRoute("topology.group"): + groupDom.setDomObj(group) + groupOrder = groupDom.getTextByTagRoute("order") + if not groupOrder: + return None + groupOrder = int(groupOrder) + if groupOrder < 1: + return None + partitionDom = XDOM() + partitionDict = {} + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + partitionName = partitionDom.getTextByTagRoute("name") + if not partitionName: + return None + partitionOrder = partitionDom.getTextByTagRoute("order") + if not partitionOrder: + return None + partitionUuid = partitionDom.getTextByTagRoute("uuid") + partitionOrder = int(partitionOrder) + if partitionOrder < 1: + return None + partitionDetails = partitionName.split(":") + if not partitionDetails or len(partitionDetails) < 1: + return None + partitionDict[partitionOrder] = { "order":partitionOrder, + "servername":partitionDetails[0], + "name":partitionDetails[1], + "uuid":partitionUuid} + groupDict[groupOrder] = partitionDict + + serverList = [] + groupOrderList = groupDict.keys() + groupOrderList.sort() + for groupOrder in groupOrderList: + partitionOrderList = groupDict[groupOrder].keys() + partitionOrderList.sort() + for partitionOrder in partitionOrderList: + serverList.append(groupDict[groupOrder][partitionOrder]) + + return serverList + + +def getSortedServerPartitionList(serverGroupElements): + serverPartitionDict = {} + groupOrderList = [] + serverList = [] + partitionDom = XDOM() + for group in serverGroupElements: + if not group: + continue + groupOrderE = group.getElementsByTagName("order") + if not (groupOrderE and groupOrderE[0].childNodes): + return None + value = int(XDOM.getText(groupOrderE[0].childNodes)) + if value > 0: + groupOrderList.append(value) + partitionDict = {} + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + + partitionName = partitionDom.getTextByTagRoute("name") + if not partitionName: + return None + partitionOrder = partitionDom.getTextByTagRoute("order") + if not partitionOrder: + return None + partitionUuid = partitionDom.getTextByTagRoute("uuid") + partitionDict[int(partitionOrder)] = [partitionName, partitionUuid] + serverPartitionDict[value] = partitionDict + groupOrderList.sort() + + for groupOrder in groupOrderList: + items = serverPartitionDict[groupOrder].items() + items.sort(key = itemgetter(0)) + serverList = serverList + [ items[i][1] for i in range(0,len(items))] + return serverList + + +def clearExportDirectory(serverList, volumeName, volumeUuid): + thisServerName = getCurrentServerName() + for exportServer in serverList: + serverName, partition = exportServer[0].split(":") + if thisServerName != serverName: + continue + partitionUuid = getUuidByDiskPartition(getDevice(partition)) + if not partitionUuid: + log("unable to find uuid of partition %s" % partition) + return False + volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid) + if os.path.exists(volumeDirName): + ## Removing /data/PARTITION-UUID/VOLUME-UUID/ + ## TODO: Get an option to remove it at this time + if runCommandFG("mv -f %s %s.delete" % (volumeDirName, volumeDirName), root=True) != 0: + return False + if runCommandFG("rm -f %s/%s/volumes/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeName), root=True) != 0: + return False + return True + + +def createExportDirectory(serverList, volumeName, volumeUuid): + thisServerName = getCurrentServerName() + tempVolumeNameFile = getTempFileName() + + try: + fp = open(tempVolumeNameFile, "w") + fp.write("VOLUME_NAME=%s\n" % volumeName) + fp.write("VOLUME_UUID=%s\n" % volumeUuid) + fp.close() + except IOError, e: + log("failed to create temporary file for volume-name: %s" % (volumeName, str(e))) + return False + + for exportServer in serverList: + serverName, partition = exportServer[0].split(":") + if thisServerName != serverName: + continue + partitionUuid = getUuidByDiskPartition(getDevice(partition)) + if not partitionUuid: + log("unable to find uuid of partition %s" % partition) + return False + + volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid) + ## Creating /data/PARTITION-UUID/VOLUME-UUID/ + if runCommandFG("mkdir %s" % volumeDirName, root=True) != 0: + return False + + ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/ + ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/brick1/ + if runCommandFG("mkdir -p %s/exports/brick1" % volumeDirName, root=True) != 0: + return False + + ## Creating /data/PARTITION-UUID/VOLUME-UUID/log/ + if runCommandFG("mkdir %s/log" % volumeDirName, root=True) != 0: + return False + + ## Creating /data/PARTITION-UUID/VOLUME-UUID/config/ + if runCommandFG("mkdir %s/config" % volumeDirName, root=True) != 0: + return False + + volumeLinkDirName = "%s/%s/volumes" % (Globals.GLUSTER_LUN_DIR, partitionUuid) + if not os.path.exists(volumeLinkDirName): + if runCommandFG("mkdir %s" % volumeLinkDirName, root=True) != 0: + return False + + ## Creating symlink + ## /data/PARTITION-UUID/volumes/VOLUME-NAME -> /data/PARTITION-UUID/VOLUME-UUID/ + command = "ln -fTs %s %s/%s" % (volumeDirName, + volumeLinkDirName, volumeName) + if runCommandFG(command, root=True) != 0: + return False + + if runCommandFG("cp -f %s %s/config/volume-name" % (tempVolumeNameFile, volumeDirName), root=True) != 0: + return False + + try: + os.remove(tempVolumeNameFile) + except OSError, e: + log("Failed to remove file %s: %s" % (tempVolumeNameFile, str(e))) + + return True + + +def getPartitionListByServerName(volumeDom, serverName, serverPartitionList=None): + partitionList = {} + if serverPartitionList: + for partitionName in serverPartitionList: + partitionUuid = getServerDiskPartitionUuid(serverName, partitionName) + if not partitionUuid: + log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName)) + return None + partitionList[partitionName] = partitionUuid + return partitionList + for group in volumeDom.getElementsByTagRoute("topology.group"): + for partitionTag in group.getElementsByTagName("partition"): + nameE = partitionTag.getElementsByTagName("name") + if not nameE: + continue + partition = XDOM.getText(nameE[0].childNodes) + if not partition: + continue + server, partitionName = partition.split(":") + if server != serverName: + continue + partitionUuid = getServerDiskPartitionUuid(serverName, partitionName) + if not partitionUuid: + log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName)) + return None + partitionList[partitionName] = partitionUuid + return partitionList + + +def isVolumeRunning(volumeName): + return Glusterd.isVolumeRunning(volumeName) + +def addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName): + migrationDom = XDOM() + if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE): + migrationDom.appendTagRoute("volume-migration") + else: + if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): + log("Failed to load volume-migration.xml file") + return None + migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration") + for tagE in migrationList: + dom = XDOM() + dom.setDomObj(tagE) + if dom.getTextByTagRoute("source-partition") == sourcePartition and \ + dom.getTextByTagRoute("destination-partition") == destinationPartition and \ + dom.getTextByTagRoute("volume-name") == volumeName: + return False + migrationTag = migrationDom.getElementsByTagRoute("volume-migration") + if not migrationTag: + return None + partitionTag = migrationDom.createTag("migration") + partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition)) + partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition)) + partitionTag.appendChild(migrationDom.createTag("volume-name", volumeName)) + migrationTag[0].appendChild(partitionTag) + if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE): + log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR) + return False + return True + + +def removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName): + migrationDom = XDOM() + if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE): + return None + if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): + log("Failed to load volume-migration.xml file") + return None + migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration") + for tagE in migrationList: + dom = XDOM() + dom.setDomObj(tagE) + if dom.getTextByTagRoute("source-partition") == sourcePartition and \ + dom.getTextByTagRoute("destination-partition") == destinationPartition and \ + dom.getTextByTagRoute("volume-name") == volumeName: + migrationDom.getElementsByTagRoute("volume-migration")[0].removeChild(tagE) + if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE): + log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR) + return False + return True + + +def addPartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None): + migrationDom = XDOM() + if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): + migrationDom.appendTagRoute("partition-migration") + else: + if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): + log("Failed to load migration.xml file") + return None + migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") + for tagE in migrationList: + dom = XDOM() + dom.setDomObj(tagE) + if dom.getTextByTagRoute("source-partition") == sourcePartition: + return False + if dom.getTextByTagRoute("destination-partition") == destinationPartition: + return False + migrationTag = migrationDom.getElementsByTagRoute("partition-migration") + if not migrationTag: + return None + partitionTag = migrationDom.createTag("migration") + partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition)) + partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition)) + migrationTag[0].appendChild(partitionTag) + if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE): + log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR) + return False + if volumeList: + for volumeName in volumeList: + addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName) + return True + + +def removePartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None): + migrationDom = XDOM() + if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): + return None + if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): + log("Failed to load migration.xml file") + return None + migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") + for tagE in migrationList: + dom = XDOM() + dom.setDomObj(tagE) + if dom.getTextByTagRoute("source-partition") == sourcePartition and \ + dom.getTextByTagRoute("destination-partition") == destinationPartition: + migrationDom.getElementsByTagRoute("partition-migration")[0].removeChild(tagE) + if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE): + log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR) + return False + if volumeList: + for volumeName in volumeList: + removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName) + return True + + +def isMigrationInProgress(partition): + migrationDom = XDOM() + if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): + return None + if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): + log("Failed to load migration.xml file") + return None + migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") + for tagE in migrationList: + dom = XDOM() + dom.setDomObj(tagE) + if migrationDom.getTextByTagRoute("source-partition") == partition or \ + migrationDom.getTextByTagRoute("destination-partition") == partition: + return True + return False + + +def getServerDiskPartitionUuid(serverName, partition): + diskConfigDom = XDOM() + if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_CONF_DIR, serverName)): + return None + for disk in diskConfigDom.getElementsByTagRoute("disks.disk"): + diskDom = XDOM() + diskDom.setDomObj(disk) + partitionList = diskDom.getElementsByTagRoute("partition") + for tagE in partitionList: + partitionDom = XDOM() + partitionDom.setDomObj(tagE) + if partitionDom.getTextByTagRoute("device") == partition: + return partitionDom.getTextByTagRoute("uuid") + + +def getVolumeServerList(requestDom, requestFlag=True): + if requestFlag: + serverGroupElementList = requestDom.getElementsByTagRoute("command.volume.topology.group") + else: + serverGroupElementList = requestDom.getElementsByTagRoute("volume.topology.group") + if not serverGroupElementList: + return None + serverList = [] + partitionDom = XDOM() + for group in serverGroupElementList: + for partition in group.getElementsByTagName("partition"): + partitionDom.setDomObj(partition) + partitionName = partitionDom.getTextByTagRoute("name") + if not partitionName: + continue + serverPartition = partitionName.split(":") + if not(len(serverPartition) > 1 and serverPartition[1]): + return None + if serverPartition[0] not in serverList: + serverList.append(serverPartition[0]) + return serverList + + +def getVolumeServerListByName(volumeName): + serverList = [] + serverDom = XDOM() + volumeDom = XDOM() + if not os.path.exists("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)): + return False + if not volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)): + return False + return getVolumeServerList(volumeDom, False) + + +def getMigrateVolumeServerPartitionInfo(volumeName): + volumeMigrationDom = XDOM() + if not volumeMigrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): + Utils.log("Failed to parse file %s" % Globals.VOLUME_MIGRATION_LIST_FILE) + return None + volumeInfo = {} + dom = XDOM() + for tagE in volumeMigrationDom.getElementsByTagRoute("volume-migration.migration"): + dom.setDomObj(tagE) + if dom.getTextByTagRoute("volume-name") == volumeName: + volumeInfo['Name'] = volumeName + volumeInfo['SourcePartition'] = dom.getTextByTagRoute("source-partition") + volumeInfo['DestinationPartition'] = dom.getTextByTagRoute("destination-partition") + return volumeInfo + return None diff --git a/src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py b/src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py new file mode 100644 index 00000000..72164ffb --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/XmlHandler.py @@ -0,0 +1,346 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def createResponseTag(self): + responseTag = self._domObj.createElement("response") + return responseTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + + +class ResponseXml(XDOM): + _responseTag = None + def __init__(self): + XDOM.__init__(self) + self._responseTag = self.createResponseTag() + self._domObj.appendChild(self._responseTag) + + @classmethod + def errorResponse(self, message): + if not self.responseTag: + return False + self.appendTagRoute("status.code", "-1"); + self.appendTagRoute("status.message", message) + + def append(self, tagName, tagValue=None): + if not self._responseTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._responseTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._responseTag: + return False + self._responseTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._responseTag: + return None + if not tagRoute: + return None + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return None + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return None + return newTagE + + def appendTagRouteOld(self, tagRoute, value=None): + if not self._responseTag: + return False + if not tagRoute: + return False + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True +##--end of ResponseXml + +def test(): + rs = ResponseXml() + rs.appendTagRoute("status.code", "0"); + rs.appendTagRoute("status.message", "SUCCESS") + serverTag = rs.appendTagRoute("server.name", "Server1") + networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface1")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40")) + networkInterfaces.appendChild(networkTag) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface2")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41")) + networkInterfaces.appendChild(networkTag) + print rs.toprettyxml() + +#test() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py new file mode 100755 index 00000000..7b9650d1 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/add_user_cifs.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils + +def main(): + if len(sys.argv) < 4: + sys.stderr.write("usage: %s UID USERNAME PASSWORD\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + uid = sys.argv[1] + userName = sys.argv[2] + password = sys.argv[3] + + if Utils.runCommand("groupadd -g %s %s" % (uid, userName)) != 0: + Utils.log("failed to add group gid:%s, name:%s\n" % (uid, userName)) + sys.exit(1) + + command = ["useradd", "-c", Globals.VOLUME_USER_DESCRIPTION, "-M", "-d", "/", "-s", "/sbin/nologin", "-u", uid, "-g", uid, userName] + if Utils.runCommand(command) != 0: + Utils.log("failed to add user uid:%s, name:%s\n" % (uid, userName)) + sys.exit(2) + + if Utils.runCommand("smbpasswd -s -a %s" % userName, + input="%s\n%s\n" % (password, password)) != 0: + Utils.log("failed to set smbpassword of user uid:%s, name:%s\n" % (uid, userName)) + sys.exit(3) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py b/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py new file mode 100755 index 00000000..96677f56 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/clear_volume_directory.py @@ -0,0 +1,97 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +import syslog +import time +from XmlHandler import ResponseXml +import DiskUtils +import Utils +from optparse import OptionParser + +def clearVolumeDirectory(diskMountPoint, volumeName, todelete): + rs = ResponseXml() + if not DiskUtils.checkDiskMountPoint(diskMountPoint): + Utils.log("failed to find disk mount point %s" % diskMountPoint) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: Mount point does not exists") + return rs.toprettyxml() + + if not os.path.exists(diskMountPoint): + rs.appendTagRoute("status.code", "-2") + rs.appendTagRoute("status.message", "Error: Mount point path does not exists") + return rs.toprettyxml() + + # clear volume directory from the disk + volumeDirectory = "%s/%s" % (diskMountPoint, volumeName) + if not os.path.exists(volumeDirectory): + rs.appendTagRoute("status.code", "-3") + rs.appendTagRoute("status.message", "Error: Volume directory does not exists") + return rs.toprettyxml() + + newVolumeDirectoryName = "%s_%s" % (volumeDirectory, time.time()) + command = ["sudo", "mv", "-f", volumeDirectory, newVolumeDirectoryName] + rv = Utils.runCommandFG(command, stdout=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to rename volume directory %s, %s" % (volumeDirectory, error)) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + + if not todelete: + rv["Status"] = "0" + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + + command = ["sudo", "rm", "-fr", newVolumeDirectoryName] + rv = Utils.runCommandFG(command, stdout=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to clear volume directory %s, %s" % (newVolumeDirectoryName, error)) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + + if not rv["Status"]: + rv["Status"] = "0" + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + +def main(): + parser = OptionParser() + parser.add_option("-d", "--delete", dest="deletedir", action="store_true", default=False, help="force delete") + (options, args) = parser.parse_args() + + if len(args) != 2: + sys.stderr.write("usage: %s [-d/--delete]\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + diskMountPoint = args[0] + volumeName = args[1] + print clearVolumeDirectory(diskMountPoint, volumeName, options.deletedir) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py new file mode 100755 index 00000000..a81b165b --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_cifs.py @@ -0,0 +1,33 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils +import VolumeUtils + +def main(): + if len(sys.argv) < 3: + sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + userList = sys.argv[2:] + + volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) + try: + os.mkdir(volumeMountDirName) + except OSError, e: + Utils.log("failed creating %s: %s\n" % (volumeMountDirName, str(e))) + sys.exit(1) + + if VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList): + sys.exit(0) + sys.exit(2) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py new file mode 100755 index 00000000..3e633697 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/create_volume_directory.py @@ -0,0 +1,82 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +from XmlHandler import ResponseXml +import DiskUtils +import Utils + +def createDirectory(disk, volumeName): + # Retrieving disk uuid + diskUuid = DiskUtils.getUuidByDiskPartition(DiskUtils.getDevice(disk)) + + rs = ResponseXml() + if not diskUuid: + Utils.log("failed to find disk:%s uuid" % disk) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: Unable to find disk uuid") + return rs.toprettyxml() + + # Retrieving disk mount point using disk uuid + diskMountPoint = DiskUtils.getMountPointByUuid(diskUuid) + if not os.path.exists(diskMountPoint): + Utils.log("failed to retrieve disk:%s mount point" % disk) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: Failed to retrieve disk details") + return rs.toprettyxml() + + # creating volume directory under disk mount point + volumeDirectory = "%s/%s" % (diskMountPoint, volumeName) + if os.path.exists(volumeDirectory): + Utils.log("Volume directory:%s already exists" % (volumeDirectory)) + rs.appendTagRoute("status.code", "-2") + rs.appendTagRoute("status.message", "Volume directory already exists!") + return rs.toprettyxml() + + if not os.path.exists(volumeDirectory): + command = ["sudo", "mkdir", volumeDirectory] + rv = Utils.runCommandFG(command, stdout=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to create volume directory %s, %s" % (volumeDirectory, error)) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + + if not rv["Status"]: + rv["Status"] = "0" + if rv["Status"] == "0": + message = volumeDirectory + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toprettyxml() + +def main(): + if len(sys.argv) != 3: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + disk = sys.argv[1] + volumeName = sys.argv[2] + print createDirectory(disk, volumeName) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py new file mode 100755 index 00000000..e5cda957 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/delete_user_cifs.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Utils + +def main(): + if len(sys.argv) < 2: + sys.stderr.write("usage: %s USERNAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + userName = sys.argv[1] + + if Utils.runCommand("userdel %s" % userName) != 0: + Utils.log("failed to remove user name:%s\n" % userName) + sys.exit(1) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py new file mode 100755 index 00000000..fd1febc9 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/delete_volume_cifs.py @@ -0,0 +1,32 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils +import VolumeUtils + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + + volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) + try: + os.rmdir(volumeMountDirName) + except OSError, e: + Utils.log("failed deleting %s: %s\n" % (volumeMountDirName, str(e))) + sys.exit(1) + + if VolumeUtils.removeVolumeCifsConfiguration(volumeName): + sys.exit(0) + sys.exit(2) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh b/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh new file mode 100755 index 00000000..07ee1a3a --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/disable-ssh-password-auth.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# disable-ssh-password-auth.sh +# Script for disabling SSH password authentication. This is used by the +# management gateway after installing the public key, so that the gluster +# node can be accessed (using ssh) only from the management gateway. +#----------------------------------------------------------------------------- + +CONFIG_FILE="/etc/ssh/sshd_config" +TIMESTAMP=`date +%d%m%Y%H%M%S` +BACKUP_FILE="${CONFIG_FILE}_${TIMESTAMP}" +TEMP_FILE="/tmp/new_sshd_config_${TIMESTAMP}" + +# Modify config file to disable password authentication, redirect to a temp file +# TODO: disable only if enabled! +sed "s/^PasswordAuthentication yes$/PasswordAuthentication no/g" ${CONFIG_FILE} > ${TEMP_FILE} + +# Secure the file by changing permissions (600) +chmod 600 ${TEMP_FILE} + +# Take backup of config file +cp ${CONFIG_FILE} ${BACKUP_FILE} + +# Overwrite config file with the modified one +mv ${TEMP_FILE} ${CONFIG_FILE} + +# Re-start ssh daemon +/etc/init.d/sshd restart + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/format_device.py b/src/com.gluster.storage.management.gateway.scripts/src/format_device.py new file mode 100755 index 00000000..3bc70532 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/format_device.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import sys +import Globals +import Utils +import DiskUtils +from optparse import OptionParser + + +def main(): + if Utils.runCommand("wget -q -O /dev/null %s" % Globals.AWS_WEB_SERVICE_URL) == 0: + sys.stderr.write("format device unsupported") + sys.exit(1) + + parser = OptionParser() + parser.add_option("-t", "--type", action="store", type="string", dest="fstype") + (options, args) = parser.parse_args() + + if len(args) != 1: + sys.stderr.write("usage: %s [-t FSTYPE] DEVICE_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + device = DiskUtils.getDevice(args[0]) + deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) + deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) + deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) + + if DiskUtils.isDataDiskPartitionFormatted(device): + sys.stderr.write("Device already formatted\n") + sys.exit(2) + + if os.path.exists(deviceFormatStatusFile): + Utils.log("format status file %s exists" % deviceFormatStatusFile) + try: + fp = open(deviceFormatStatusFile) + line = fp.read() + fp.close() + if line.strip().upper() == "COMPLETED": + sys.stderr.write("Device already formatted\n") + sys.exit(3) + else: + sys.stderr.write("Device format already running\n") + sys.exit(4) + except IOError, e: + Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e))) + sys.stderr.write("%s\n" % str(e)) + sys.exit(-2) + + if os.path.exists(deviceFormatLockFile): + Utils.log("lock file %s exists" % deviceFormatLockFile) + sys.stderr.write("Device format already running\n") + sys.exit(5) + + if options.fstype: + command = ["gluster_provision_block_wrapper.py", "-t", "%s" % (options.fstype), "%s" % (device)] + else: + command = ["gluster_provision_block_wrapper.py", "%s" % (device)] + + try: + pid = os.fork() + except OSError, e: + Utils.log("failed to fork a child process: %s" % str(e)) + sys.exit(6) + if pid == 0: + os.execv("/usr/sbin/gluster_provision_block_wrapper.py", command) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py new file mode 100755 index 00000000..cf84080b --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_brick_status.py @@ -0,0 +1,40 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Console. +# + +import os +import sys +import Utils + +def main(): + if len(sys.argv) != 3: + sys.stderr.write("usage: %s VOLUME_NAME BRICK_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + brickName = sys.argv[2] + pidFile = "/etc/glusterd/vols/%s/run/%s.pid" % (volumeName, brickName.replace(":", "").replace("/", "-")) + + if not os.path.exists(pidFile): + print "OFFLINE" + else: + try: + fp = open(pidFile) + pidString = fp.readline() + fp.close() + os.getpgid(int(pidString)) + print "ONLINE" + except IOError, e: + Utils.log("failed to open file %s: %s" % (pidFile, str(e))) + print "UNKNOWN" + except ValueError, e: + Utils.log("invalid pid %s in file %s: %s" % (pidString, pidFile, str(e))) + print "UNKNOWN" + except OSError, e: + #Utils.log("failed to get process detail of pid %s: %s" % (pidString, str(e))) + print "OFFLINE" + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py new file mode 100755 index 00000000..2f4a39c3 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_mount_point.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import Utils +from DiskUtils import * +from XmlHandler import ResponseXml + + +def getmountpoint(path): + if not path: + Utils.log("Not a valid path:%s" % path) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: given path name is empty") + return rs.toprettyxml() + + rs = ResponseXml() + mountPoint = None + + for line in readFsTab(): + if path.startswith(line['MountPoint']): + if not mountPoint: + mountPoint = line['MountPoint'] + if len(line['MountPoint']) > len(mountPoint): + mountPoint = line['MountPoint'] + + if "/" == mountPoint or not mountPoint: + Utils.log("failed to find mount point of the given path:%s" % path) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: Unable to find disk mount point") + return rs.toprettyxml() + + rs.appendTagRoute("status.code", "0") + rs.appendTagRoute("status.message", mountPoint) + return rs.toprettyxml() + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + path = sys.argv[1] + print getmountpoint(path) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py new file mode 100755 index 00000000..08e80b7e --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_disk_name_by_path.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import Utils +from DiskUtils import * +from XmlHandler import ResponseXml + + +def getmountpoint(path): + if not path: + Utils.log("Not a valid path:%s" % path) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: given path name is empty") + return rs.toprettyxml() + + rs = ResponseXml() + mountPoint = None + fsTabEntry = None + for line in readFsTab(): + if path.startswith(line['MountPoint']): + if not mountPoint: + mountPoint = line['MountPoint'] + fsTabEntry = line + if len(line['MountPoint']) > len(mountPoint): + mountPoint = line['MountPoint'] + fsTabEntry = line + + if "/" == mountPoint or not mountPoint: + Utils.log("failed to find mount point of the given path:%s" % path) + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "Error: Unable to find disk mount point") + return rs.toprettyxml() + + rs.appendTagRoute("status.code", "0") + if fsTabEntry["Device"].startswith("UUID="): + rs.appendTagRoute("status.message", getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1])) + else: + rs.appendTagRoute("status.message", "Unable to find disk name") + return rs.toprettyxml() + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + path = sys.argv[1] + print getmountpoint(path) + sys.exit(0) + +if __name__ == "__main__": + main() + diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_file.py b/src/com.gluster.storage.management.gateway.scripts/src/get_file.py new file mode 100755 index 00000000..61c33eba --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_file.py @@ -0,0 +1,130 @@ +# Copyright (C) 2009,2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import Globals +import Utils +from VolumeUtils import * +from XmlHandler import ResponseXml + + +def enumLogType(logCode): + if "M" == logCode.upper(): + return "EMERGENCY" + elif "A" == logCode.upper(): + return "ALERT" + elif "C" == logCode.upper(): + return "CRITICAL" + elif "E" == logCode.upper(): + return "ERROR" + elif "W" == logCode.upper(): + return "WARNING" + elif "N" == logCode.upper(): + return "NOTICE" + elif "I" == logCode.upper(): + return "INFO" + elif "D" == logCode.upper(): + return "DEBUG" + elif "T" == logCode.upper(): + return "TRACE" + else: + return "UNKNOWN" +##--end of enumLogType() + + +def addLog(responseDom, logMessageTag, loginfo): + logTag = responseDom.createTag("log", None) + logTag.appendChild(responseDom.createTag("date", loginfo[0])) + logTag.appendChild(responseDom.createTag("time", loginfo[1])) + logTag.appendChild(responseDom.createTag("type", enumLogType(loginfo[2]))) + logTag.appendChild(responseDom.createTag("message", loginfo[3])) + logMessageTag.appendChild(logTag) + return True +##--end of addLog() + + +def logSplit(log): + loginfo = log.strip().split(None, 3) + loginfo[0] = loginfo[0][1:] #-- Remove '[' + loginfo[1] = loginfo[1][0:-1] #-- Remove ']' + return loginfo +##--end of logSplit() + + +def getVolumeLog(volumeName, tailCount): + rs = ResponseXml() + if not volumeName: + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "No volume name given") + return rs.toprettyxml() + + if not tailCount: + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "No tail count given") + return rs.toprettyxml() + + thisServerName = getCurrentServerName() + if not thisServerName: + rs.appendTagRoute("status.code", "-2") + rs.appendTagRoute("status.message", "Failed to get current server name") + return rs.toprettyxml() + + volumeDom = XDOM() + partitionList = getPartitionListByServerName(volumeDom, thisServerName) + if not partitionList: + rs.appendTagRoute("status.code", "-3") + rs.appendTagRoute("status.message", "Failed to get server partition details") + return rs.toprettyxml() + + pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' + logMessagesTag = rs.createTag("response.logMessages") + for partitionName in partitionList: + logMessageTag = rs.createTag("logMessage") + logMessageTag.appendChild("disk", "%s:%s" % (thisServerName, partitionName)) + + logDirectory = "%s/%s/%s/log" % (Globals.GLUSTER_LUN_DIR, partitionList[partitionName], volumeUuid) + logFileName = "%s/%s-%s-%s-exports-brick1.log" % (logDirectory, + Globals.GLUSTER_LUN_DIR[1:], + partitionList[partitionName], + volumeUuid) + if not os.path.exists(logFileName): + Utils.log("volume log file not found %s" % logFileName) + continue + fp = open(logFileName) + lines = [line for line in fp if re.match(pattern, line)] + fp.close() + i = len(lines) - int(tailCount) + if i < 0: + i = 0 + for log in lines[i:]: + loginfo = logSplit(log) + addLog(rs, logMessageTag, loginfo) + logMessagesTag.appendChild(logMessageTag) + return rs.toprettyxml() +##--end of getVolumeLog() + +def main(): + if len(sys.argv) != 3: + print >> sys.stderr, "usage: %s " % sys.argv[0] + sys.exit(-1) + + volumeName = sys.argv[1] + tailCount = sys.argv[2] + print getVolumeLog(volumeName, tailCount) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py new file mode 100755 index 00000000..57fc0455 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_format_device_status.py @@ -0,0 +1,124 @@ +#!/usr/bin/python +# Copyright (C) 2009,2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import sys +import time +import Utils +import DiskUtils +from XmlHandler import ResponseXml + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s DEVICE_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + device = DiskUtils.getDevice(sys.argv[1]) + + deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) + deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) + deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) + + time.sleep(1) + if not os.path.exists(deviceFormatLockFile): + if not os.path.exists(deviceFormatStatusFile): + sys.stderr.write("Device format not initiated\n") + sys.exit(1) + + if os.path.exists(deviceFormatStatusFile): + try: + fp = open(deviceFormatStatusFile) + line = fp.read() + fp.close() + line = line.strip() + + Utils.removeFile(deviceFormatOutputFile) + Utils.removeFile(deviceFormatStatusFile) + + responseDom = ResponseXml() + responseDom.appendTagRoute("device", sys.argv[1]) + responseDom.appendTagRoute("completedBlocks", "0") + responseDom.appendTagRoute("totalBlocks", "0") + responseDom.appendTagRoute("message", line) + if line.upper() == "COMPLETED": + responseDom.appendTagRoute("formatStatus", "COMPLETED") + else: + responseDom.appendTagRoute("formatStatus", "NOT_RUNNING") + print responseDom.toxml() + sys.exit(0) + except IOError, e: + Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e))) + sys.stderr.write("%s\n" % str(e)) + sys.exit(-2) + + if not os.path.exists(deviceFormatOutputFile): + responseDom = ResponseXml() + responseDom.appendTagRoute("device", sys.argv[1]) + responseDom.appendTagRoute("completedBlocks", "0") + responseDom.appendTagRoute("totalBlocks", "0") + responseDom.appendTagRoute("message", None) + responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") + print responseDom.toxml() + sys.exit(0) + + try: + fp = open(deviceFormatOutputFile) + content = fp.read() + fp.close() + except IOError, e: + Utils.log("failed to read format output file %s: %s" % (deviceFormatOutputFile, str(e))) + responseDom = ResponseXml() + responseDom.appendTagRoute("device", sys.argv[1]) + responseDom.appendTagRoute("completedBlocks", "0") + responseDom.appendTagRoute("totalBlocks", "0") + responseDom.appendTagRoute("message", None) + responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") + print responseDom.toxml() + sys.exit(0) + + lines = [line for line in content + if "Writing inode tables" in line] + if not lines: + responseDom = ResponseXml() + responseDom.appendTagRoute("device", sys.argv[1]) + responseDom.appendTagRoute("completedBlocks", "0") + responseDom.appendTagRoute("totalBlocks", "0") + if content: + responseDom.appendTagRoute("message", content[-1]) + else: + responseDom.appendTagRoute("message") + responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") + print responseDom.toxml() + sys.exit(0) + + tokens = [token for token in lines[-1].split("\x08") if token] + if "done" in tokens[-1]: + values = tokens[-2].split(':')[-1].strip().split('/') + else: + values = tokens[-1].split(':')[-1].strip().split('/') + + responseDom.appendTagRoute("device", sys.argv[1]) + responseDom.appendTagRoute("completedBlocks", values[0]) + responseDom.appendTagRoute("totalBlocks", values[1]) + responseDom.appendTagRoute("message", lines[-1]) + responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") + print responseDom.toxml() + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py new file mode 100755 index 00000000..546aec31 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_cpu_details.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +from XmlHandler import ResponseXml +import Utils + +def getCpuData(period): + cpuRrdFile = "/var/lib/rrd/cpu.rrd" + rs = ResponseXml() + command = "rrdtool xport --start -%s \ + DEF:cpuuser=%s:user:AVERAGE \ + DEF:cpusystem=%s:system:AVERAGE \ + CDEF:total=cpuuser,cpusystem,+ \ + XPORT:cpuuser:user \ + XPORT:cpusystem:system \ + XPORT:total:total" % (period, cpuRrdFile, cpuRrdFile) + + rv = Utils.runCommand(command, output=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to create RRD file for cpu usages %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return rv["Stdout"] + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + period = sys.argv[1] + print getCpuData(period) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py new file mode 100755 index 00000000..f7c3031b --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_memory_details.py @@ -0,0 +1,89 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +# Input command: get_rrd_memory_details.py 1hour +# OUTPUT as bellow: +# +# +# +# +# 1310455500 +# 300 +# 1310459100 +# 13 +# 5 +# +# memoryUsed +# memoryFree +# memoryCache +# memoryBuffer +# totalMemory +# +# +# +# 13104555001.9181091707e+061.5819754974e+061.2528146351e+061.2528146351e+063.5000846681e+06 +# --- +# --- +# +# + +import os +import sys +import syslog +from XmlHandler import ResponseXml +import Utils + +def getMemData(period): + memRrdFile = "/var/lib/rrd/mem.rrd" + rs = ResponseXml() + command = "rrdtool xport --start -%s \ + DEF:free=%s:memfree:AVERAGE \ + DEF:used=%s:memused:AVERAGE \ + DEF:cache=%s:memcache:AVERAGE \ + DEF:buffer=%s:membuffer:AVERAGE \ + CDEF:total1=used,free,+ \ + CDEF:used1=used,buffer,cache,-,- \ + CDEF:total=total1,used1,+ \ + XPORT:used:memoryUsed \ + XPORT:free:memoryFree \ + XPORT:cache:memoryCache \ + XPORT:buffer:memoryBuffer \ + XPORT:total:totalMemory" % (period, memRrdFile, memRrdFile, memRrdFile, memRrdFile) + + rv = Utils.runCommand(command, output=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to create RRD file for memory usages %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return rv["Stdout"] + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + period = sys.argv[1] + print getMemData(period) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py new file mode 100755 index 00000000..6a31cde8 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_rrd_net_details.py @@ -0,0 +1,52 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +from XmlHandler import ResponseXml +import Utils + +def main(): + if len(sys.argv) != 3: + sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + device = sys.argv[1] + period = sys.argv[2] + + rs = ResponseXml() + command = "rrdtool xport --start -%s \ + DEF:received=/var/lib/rrd/network-%s.rrd:received:AVERAGE \ + DEF:transmitted=/var/lib/rrd/network-%s.rrd:transmitted:AVERAGE \ + CDEF:total=received,transmitted,+ \ + XPORT:received:received \ + XPORT:transmitted:transmitted \ + XPORT:total:total" % (period, device, device) + rv = Utils.runCommand(command, output=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to get RRD information of device %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + print rs.toxml() + print rv["Stdout"] + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py b/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py new file mode 100755 index 00000000..9c3da741 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_server_details.py @@ -0,0 +1,118 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import socket +import re +import Utils +import DiskUtils +from NetworkUtils import * +from Disk import * +from XmlHandler import ResponseXml +from optparse import OptionParser + + +def getServerDetails(listall): + serverName = socket.gethostname() + meminfo = getMeminfo() + cpu = getCpuUsageAvg() + nameServerList, domain, searchDomain = readResolvConfFile() + if not domain: + domain = [None] + + responseDom = ResponseXml() + serverTag = responseDom.appendTagRoute("server") + serverTag.appendChild(responseDom.createTag("name", serverName)) + serverTag.appendChild(responseDom.createTag("domainname", domain[0])) + if Utils.runCommand("pidof glusterd") == 0: + serverTag.appendChild(responseDom.createTag("status", "ONLINE")) + else: + serverTag.appendChild(responseDom.createTag("status", "OFFLINE")) + serverTag.appendChild(responseDom.createTag("cpuUsage", str(cpu))) + serverTag.appendChild(responseDom.createTag("totalMemory", str(convertKbToMb(meminfo['MemTotal'])))) + serverTag.appendChild(responseDom.createTag("memoryInUse", str(convertKbToMb(meminfo['MemUsed'])))) + serverTag.appendChild(responseDom.createTag("uuid", None)) + + for dns in nameServerList: + serverTag.appendChild(responseDom.createTag("dns%s" % str(nameServerList.index(dns) +1) , dns)) + + #TODO: probe and retrieve timezone, ntp-server details and update the tags + + deviceList = {} + interfaces = responseDom.createTag("networkInterfaces", None) + for device in getNetDeviceList(): + if device["model"] in ['LOCAL', 'IPV6-IN-IPV4']: + continue + deviceList[device["device"]] = device + try: + macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() + except IOError: + continue + interfaceTag = responseDom.createTag("networkInterface", None) + interfaceTag.appendChild(responseDom.createTag("name", device["device"])) + interfaceTag.appendChild(responseDom.createTag("hwAddr",macAddress)) + interfaceTag.appendChild(responseDom.createTag("speed", device["speed"])) + interfaceTag.appendChild(responseDom.createTag("model", device["model"])) + if deviceList[device["device"]]: + if deviceList[device["device"]]["onboot"]: + interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) + else: + interfaceTag.appendChild(responseDom.createTag("onBoot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootProto", deviceList[device["device"]]["bootproto"])) + interfaceTag.appendChild(responseDom.createTag("ipAddress", deviceList[device["device"]]["ipaddr"])) + interfaceTag.appendChild(responseDom.createTag("netMask", deviceList[device["device"]]["netmask"])) + interfaceTag.appendChild(responseDom.createTag("defaultGateway", deviceList[device["device"]]["gateway"])) + if deviceList[device["device"]]["mode"]: + interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) + if deviceList[device["device"]]["master"]: + interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) + spliter = re.compile(r'[\D]') + interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) + else: + interfaceTag.appendChild(responseDom.createTag("onBoot", "no")) + interfaceTag.appendChild(responseDom.createTag("bootProto", "none")) + interfaces.appendChild(interfaceTag) + serverTag.appendChild(interfaces) + + responseDom.appendTag(serverTag) + serverTag.appendChild(responseDom.createTag("numOfCPUs", int(os.sysconf('SC_NPROCESSORS_ONLN')))) + + diskDom = DiskUtils.getDiskDom() + if not diskDom: + sys.stderr.write("No disk found!") + Utils.log("Failed to get disk details") + sys.exit(1) + + serverTag.appendChild(diskDom.getElementsByTagRoute("disks")[0]) + return serverTag + +def main(): + parser = OptionParser() + parser.add_option("-N", "--only-data-disks", + action="store_false", dest="listall", default=True, + help="List only data disks") + + (options, args) = parser.parse_args() + responseXml = getServerDetails(options.listall) + if responseXml: + print responseXml.toxml() + + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py b/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py new file mode 100755 index 00000000..a57428b6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_server_status.py @@ -0,0 +1,22 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Console. +# + +import os +import sys +import Utils + +def main(): + if len(sys.argv) != 1: + sys.stderr.write("usage: %s\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + if Utils.runCommand("pidof glusterd") == 0: + print "ONLINE" + else: + print "OFFLINE" + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py new file mode 100755 index 00000000..fd7361da --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_brick_log.py @@ -0,0 +1,103 @@ +#!/usr/bin/python +# Copyright (C) 2009,2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import re +import os +import sys +from XmlHandler import XDOM + +def enumLogType(logCode): + if "M" == logCode.upper(): + return "EMERGENCY" + elif "A" == logCode.upper(): + return "ALERT" + elif "C" == logCode.upper(): + return "CRITICAL" + elif "E" == logCode.upper(): + return "ERROR" + elif "W" == logCode.upper(): + return "WARNING" + elif "N" == logCode.upper(): + return "NOTICE" + elif "I" == logCode.upper(): + return "INFO" + elif "D" == logCode.upper(): + return "DEBUG" + elif "T" == logCode.upper(): + return "TRACE" + else: + return "UNKNOWN" +##--end of enumLogType() + +def addLog(responseDom, logMessagesTag, loginfo): + logMessageTag = responseDom.createTag("logMessage") + logMessageTag.appendChild(responseDom.createTag("timestamp", loginfo[0] + " " + loginfo[1])) + logMessageTag.appendChild(responseDom.createTag("severity", enumLogType(loginfo[2]))) + logMessageTag.appendChild(responseDom.createTag("message", loginfo[3])) + logMessagesTag.appendChild(logMessageTag); + return True +##--end of addLog() + +def logSplit(log): + loginfo = log.strip().split(None, 3) + loginfo[0] = loginfo[0][1:] #-- Remove '[' + loginfo[1] = loginfo[1][0:-1] #-- Remove ']' + return loginfo +##--end of logSplit() + +def getVolumeLog(logFilePath, tailCount): + rs = XDOM() + if not logFilePath: + print >> sys.stderr, "No log file path given" + sys.exit(-1); + + if not tailCount: + print >> sys.stderr, "No tail count given" + sys.exit(-1); + + pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' + if not os.path.exists(logFilePath): + print >> sys.stderr, "volume log file [%s] not found!" % logFilePath + sys.exit(-1); + + fp = open(logFilePath) + lines = [line for line in fp if re.match(pattern, line)] + fp.close() + i = len(lines) - int(tailCount) + if i < 0: + i = 0 + logMessagesTag = rs.createTag("logMessages") + rs.addTag(logMessagesTag) + for log in lines[i:]: + loginfo = logSplit(log) + addLog(rs, logMessagesTag, loginfo) + return rs.toxml() +##--end of getVolumeLog() + +def main(): + if len(sys.argv) != 3: + print >> sys.stderr, "usage: %s " % sys.argv[0] + sys.exit(-1) + + logFilePath = sys.argv[1] + tailCount = sys.argv[2] + print getVolumeLog(logFilePath, tailCount) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py new file mode 100755 index 00000000..b906c002 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/get_volume_log.py @@ -0,0 +1,131 @@ +# Copyright (C) 2009,2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import Globals +import syslog +import Utils +from VolumeUtils import * +from XmlHandler import ResponseXml + + +def enumLogType(logCode): + if "M" == logCode.upper(): + return "EMERGENCY" + elif "A" == logCode.upper(): + return "ALERT" + elif "C" == logCode.upper(): + return "CRITICAL" + elif "E" == logCode.upper(): + return "ERROR" + elif "W" == logCode.upper(): + return "WARNING" + elif "N" == logCode.upper(): + return "NOTICE" + elif "I" == logCode.upper(): + return "INFO" + elif "D" == logCode.upper(): + return "DEBUG" + elif "T" == logCode.upper(): + return "TRACE" + else: + return "UNKNOWN" +##--end of enumLogType() + + +def addLog(responseDom, logMessageTag, loginfo): + logTag = responseDom.createTag("log", None) + logTag.appendChild(responseDom.createTag("date", loginfo[0])) + logTag.appendChild(responseDom.createTag("time", loginfo[1])) + logTag.appendChild(responseDom.createTag("type", enumLogType(loginfo[2]))) + logTag.appendChild(responseDom.createTag("message", loginfo[3])) + logMessageTag.appendChild(logTag) + return True +##--end of addLog() + + +def logSplit(log): + loginfo = log.strip().split(None, 3) + loginfo[0] = loginfo[0][1:] #-- Remove '[' + loginfo[1] = loginfo[1][0:-1] #-- Remove ']' + return loginfo +##--end of logSplit() + + +def getVolumeLog(volumeName, tailCount): + rs = ResponseXml() + if not volumeName: + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "No volume name given") + return rs.toprettyxml() + + if not tailCount: + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "No tail count given") + return rs.toprettyxml() + + thisServerName = getCurrentServerName() + if not thisServerName: + rs.appendTagRoute("status.code", "-2") + rs.appendTagRoute("status.message", "Failed to get current server name") + return rs.toprettyxml() + + volumeDom = XDOM() + partitionList = getPartitionListByServerName(volumeDom, thisServerName) + if not partitionList: + rs.appendTagRoute("status.code", "-3") + rs.appendTagRoute("status.message", "Failed to get server partition details") + return rs.toprettyxml() + + pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' + logMessagesTag = rs.createTag("response.logMessages") + for partitionName in partitionList: + logMessageTag = rs.createTag("logMessage") + logMessageTag.appendChild("disk", "%s:%s" % (thisServerName, partitionName)) + + logDirectory = "%s/%s/%s/log" % (Globals.GLUSTER_LUN_DIR, partitionList[partitionName], volumeUuid) + logFileName = "%s/%s-%s-%s-exports-brick1.log" % (logDirectory, + Globals.GLUSTER_LUN_DIR[1:], + partitionList[partitionName], + volumeUuid) + if not os.path.exists(logFileName): + Utils.log("volume log file not found %s" % logFileName) + continue + fp = open(logFileName) + lines = [line for line in fp if re.match(pattern, line)] + fp.close() + i = len(lines) - int(tailCount) + if i < 0: + i = 0 + for log in lines[i:]: + loginfo = logSplit(log) + addLog(rs, logMessageTag, loginfo) + logMessagesTag.appendChild(logMessageTag) + return rs.toprettyxml() +##--end of getVolumeLog() + +def main(): + if len(sys.argv) != 3: + print >> sys.stderr, "usage: %s " % sys.argv[0] + sys.exit(-1) + + volumeName = sys.argv[1] + tailCount = sys.argv[2] + print getVolumeLog(volumeName, tailCount) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py b/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py new file mode 100755 index 00000000..a3b2776d --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/gluster_provision_block_wrapper.py @@ -0,0 +1,109 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import sys +import subprocess +import Utils +import DiskUtils +from optparse import OptionParser + +def writeStatus(deviceFormatStatusFile, message): + try: + fp = open(deviceFormatStatusFile, "w") + fp.write(message) + fp.close() + except IOError, e: + Utils.log("Failed to update log file %s: %s" % (deviceFormatStatusFile, str(e))) + return False + return True + + +def main(): + parser = OptionParser() + parser.add_option("-t", "--type", action="store", type="string", dest="fstype") + (options, args) = parser.parse_args() + + if len(args) != 1: + sys.stderr.write("usage: %s [-t FSTYPE] DEVICE" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + device = args[0] + deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) + deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) + deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) + + if os.path.exists(deviceFormatStatusFile): + Utils.log("device format status file %s exists" % deviceFormatStatusFile) + sys.exit(1) + + if os.path.exists(deviceFormatLockFile): + Utils.log("device format lock file %s exists" % deviceFormatLockFile) + sys.exit(2) + + try: + fp = open(deviceFormatLockFile, "w") + fp.close() + except OSError, e: + Utils.log("failed to create lock file %s: %s" % (deviceFormatLockFile, str(e))) + writeStatus(deviceFormatStatusFile, "Lock file creation failed\n") + sys.exit(3) + + try: + fptr = open(deviceFormatOutputFile, 'w') + except IOError, e: + Utils.log("failed to create output file %s" % deviceFormatOutputFile) + writeStatus(deviceFormatStatusFile, "Output file creation failed\n") + Utils.removeFile(deviceFormatLockFile) + sys.exit(4) + + if options.fstype: + command = "gluster-provision-block -t %s %s" % (options.fstype, device) + else: + command = "gluster-provision-block %s" % (device) + + process = Utils.runCommandBG(command, + stdinFileObj=subprocess.PIPE, + stdoutFileObj=fptr, + stderrFileObj=subprocess.PIPE) + if process: + status = process.wait() + else: + Utils.removeFile(deviceFormatOutputFile) + Utils.removeFile(deviceFormatLockFile) + writeStatus(deviceFormatStatusFile, "Device format failed\n") + sys.exit(5) + + if status != 0: + Utils.removeFile(deviceFormatOutputFile) + Utils.removeFile(deviceFormatLockFile) + writeStatus(deviceFormatStatusFile, "Device format failed\n") + sys.exit(6) + + if Utils.runCommand("/sbin/udevtrigger") != 0: + Utils.log("failed running /sbin/udevtrigger") + + if Utils.runCommand("/usr/bin/lshal") != 0: + Utils.log("failed running /usr/bin/lshal") + writeStatus(deviceFormatStatusFile, "Completed\n") + Utils.removeFile(deviceFormatOutputFile) + Utils.removeFile(deviceFormatLockFile) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py new file mode 100755 index 00000000..f6bacfc4 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/modify_volume_cifs.py @@ -0,0 +1,28 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Utils +import VolumeUtils + +def main(): + if len(sys.argv) <= 2: + sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + userList = sys.argv[2:] + + if not VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList): + sys.exit(1) + if Utils.runCommand("service smb reload") != 0: + Utils.log("Failed to reload smb service") + sys.exit(2) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py b/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py new file mode 100644 index 00000000..18cf89ae --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import os +import string +import time +import Utils +import socket +import struct +import Globals +from XmlHandler import * + +def isInPeer(): + command = "gluster peer status" + status = Utils.runCommand(command, output=True, root=True) + if status["Status"] == 0: + if status["Stdout"].strip().upper() != "NO PEERS PRESENT": + return True + return False + Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) + return False + +def response(multiCastGroup, port): + # waiting for the request! + socketRequest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketRequest.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketRequest.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + socketRequest.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + + #TODO: Remove infinite loop and make this as a deamon (service) + while True: + request = socketRequest.recvfrom(1024) + if not request: + continue + dom = XDOM() + dom.parseString(request[0]) + if not dom: + continue + if not dom.getTextByTagRoute("request.name"): + continue + requesttime = dom.getTextByTagRoute("request.time") + if not requesttime: + continue + if isInPeer(): + time.sleep(5) + continue + socketSend.sendto("%s" % (socket.gethostname(), requesttime), + (multiCastGroup, port)) + request = None + +def main(): + response(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl new file mode 100755 index 00000000..7b070812 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_cpu.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +use RRDs; + +my $rrdlog = '/var/lib/rrd'; +my $graphs = '/var/lib/rrd'; + +updatecpudata(); +#updatecpugraph('day'); +#updatecpugraph('week'); +#updatecpugraph('month'); +#updatecpugraph('year'); + +sub updatecpugraph { + my $period = $_[0]; + + RRDs::graph ("$graphs/cpu-$period.png", + "--start", "-1$period", "-aPNG", "-i", "-z", + "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", + "--color", "SHADEA#FFFFFF", + "--color", "SHADEB#FFFFFF", + "--color", "BACK#FFFFFF", + "-t cpu usage per $period", + "DEF:user=$rrdlog/cpu.rrd:user:AVERAGE", + "DEF:system=$rrdlog/cpu.rrd:system:AVERAGE", + "DEF:idle=$rrdlog/cpu.rrd:idle:AVERAGE", + + "CDEF:total=user,system,idle,+,+", + "CDEF:userpct=100,user,total,/,*", + "CDEF:systempct=100,system,total,/,*", + "CDEF:idlepct=100,idle,total,/,*", + + "AREA:userpct#0000FF:User cpu usage\\j", + "STACK:systempct#FF0000:system cpu usage\\j", + "STACK:idlepct#00FF00:idle cpu usage\\j"); + + # "GPRINT:userpct:MAX:maximal user cpu\\:%3.2lf%%", + # "GPRINT:userpct:AVERAGE:average user cpu\\:%3.2lf%%", + # "GPRINT:userpct:LAST:current user cpu\\:%3.2lf%%\\j", + # "GPRINT:systempct:MAX:maximal system cpu\\:%3.2lf%%", + # "GPRINT:systempct:AVERAGE:average system cpu\\:%3.2lf%%", + # "GPRINT:systempct:LAST:current system cpu\\:%3.2lf%%\\j", + # "GPRINT:idlepct:MAX:maximal idle cpu\\:%3.2lf%%", + # "GPRINT:idlepct:AVERAGE:average idle cpu\\:%3.2lf%%", + # "GPRINT:idlepct:LAST:current idle cpu\\:%3.2lf%%\\j"); + $ERROR = RRDs::error; + print "Error in RRD::graph for cpu: $ERROR\n" if $ERROR; +} + +sub updatecpudata { + if ( ! -e "$rrdlog/cpu.rrd") { + RRDs::create ("$rrdlog/cpu.rrd", "--step=300", + "DS:user:COUNTER:600:0:U", + "DS:system:COUNTER:600:0:U", + "DS:idle:COUNTER:600:0:U", + + "RRA:AVERAGE:0.5:1:576", + "RRA:AVERAGE:0.5:6:672", + "RRA:AVERAGE:0.5:24:732", + "RRA:AVERAGE:0.5:144:1460"); + $ERROR = RRDs::error; + print "Error in RRD::create for cpu: $ERROR\n" if $ERROR; + } + + my ($cpu, $user, $nice, $system,$idle); + + open STAT, "/proc/stat"; + while() { + chomp; + /^cpu\s/ or next; + ($cpu, $user, $nice, $system, $idle) = split /\s+/; + last; + } + close STAT; + $user += $nice; + + RRDs::update ("$rrdlog/cpu.rrd", + "-t", "user:system:idle", + "N:$user:$system:$idle"); + $ERROR = RRDs::error; + print "Error in RRD::update for cpu: $ERROR\n" if $ERROR; + + print "N:$user:$system:$idle\n"; +} diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl new file mode 100755 index 00000000..5c47cd81 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_mem.pl @@ -0,0 +1,100 @@ +#!/usr/bin/perl + +use RRDs; + +my $rrdlog = '/var/lib/rrd'; +my $graphs = '/var/lib/rrd'; + +updatememdata (); +#updatememgraph ('day'); +#updatememgraph ('week'); +#updatememgraph ('month'); +#updatememgraph ('year'); + +sub updatememgraph { + my $period = $_[0]; + + RRDs::graph ("$graphs/memory-$period.png", + "--start", "-1$period", "-aPNG", "-i", "-z", + "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", + "--color", "SHADEA#FFFFFF", + "--color", "SHADEB#FFFFFF", + "--color", "BACK#FFFFFF", + "-t memory usage per $period", + "DEF:used=$rrdlog/mem.rrd:memused:AVERAGE", + "DEF:free=$rrdlog/mem.rrd:memfree:AVERAGE", + "DEF:cache=$rrdlog/mem.rrd:memcache:AVERAGE", + "CDEF:total=used,free,+", + "CDEF:used1=used,buffer,cache,-,-", + "CDEF:usedpct=100,used1,total,/,*", + "CDEF:free1=total,used1,-", + "CDEF:cachepct=100,cache,total,/,*", + "CDEF:freepct=100,free1,total,/,*", + "AREA:usedpct#0000FF:used memory\\j", + "STACK:cachepct#FFFF00:cached memory\\j", + "STACK:freepct#00FF00:free memory\\j"); + $ERROR = RRDs::error; + print "Error in RRD::graph for mem: $ERROR\n" if $ERROR; + + RRDs::graph ("$graphs/swap-$period.png", + "--start", "-1$period", "-aPNG", "-i", "-z", + "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", + "--color", "SHADEA#FFFFFF", + "--color", "SHADEB#FFFFFF", + "--color", "BACK#FFFFFF", + "-t swap usage per $period", + "DEF:used=$rrdlog/mem.rrd:swapused:AVERAGE", + "DEF:free=$rrdlog/mem.rrd:swapfree:AVERAGE", + "CDEF:total=used,free,+", + "CDEF:usedpct=100,used,total,/,*", + "CDEF:freepct=100,free,total,/,*", + "AREA:usedpct#0000FF:used swap\\j", + "STACK:freepct#00FF00:free swap\\j"); + $ERROR = RRDs::error; + print "Error in RRD::graph for swap: $ERROR\n" if $ERROR; +} + +sub updatememdata { + my ($memused, $memfree, $memshared, $membuffers, $memcache, $swapused, $swapfree); + if ( ! -e "$rrdlog/mem.rrd") { + RRDs::create ("$rrdlog/mem.rrd", "--step=300", + "DS:memused:ABSOLUTE:600:0:U", + "DS:memfree:ABSOLUTE:600:0:U", + "DS:memcache:ABSOLUTE:600:0:U", + "DS:membuffer:ABSOLUTE:600:0:U", + "DS:swapused:ABSOLUTE:600:0:U", + "DS:swapfree:ABSOLUTE:600:0:U", + "RRA:AVERAGE:0.5:1:576", + "RRA:AVERAGE:0.5:6:672", + "RRA:AVERAGE:0.5:24:732", + "RRA:AVERAGE:0.5:144:1460"); + $ERROR = RRDs::error; + print "Error in RRD::create for mem: $ERROR\n" if $ERROR; + } + + my @memdata = `free -b -o`; + + my $temp = $memdata[1]; + + chomp( $temp ); + my @tempa = split (/\s+/, $temp); + $memused = $tempa [2]; + $memfree = $tempa [3]; + $memshared = $tempa [4]; + $membuffers = $tempa [5]; + $memcache = $tempa [6]; + + $temp = $memdata[2]; + chomp( $temp ); + @tempa = split (/\s+/, $temp); + $swapused = $tempa [2]; + $swapfree = $tempa [3]; + + + RRDs::update ("$rrdlog/mem.rrd", + "-t", "memused:memfree:memcache:membuffer:swapused:swapfree", + "N:$memused:$memfree:$memcache:$membuffers:$swapused:$swapfree"); + + $ERROR = RRDs::error; + print "Error in RRD::update for mem: $ERROR\n" if $ERROR; +} diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl b/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl new file mode 100755 index 00000000..03f4f492 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_net.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl + +use RRDs; + +my $rrdlog = '/var/lib/rrd'; +my $graphs = '/var/lib/rrd'; + +updatenetdata(); +#updatenetgraph('hour'); +#updatenetgraph('day'); +#updatenetgraph('week'); +#updatenetgraph('month'); +#updatenetgraph('year'); + +sub updatenetgraph { + my $period = $_[0]; + + foreach $rrdfile (<$rrdlog/network-*.rrd>) { + RRDs::graph ("$graphs/network-$device-$period.png", + "--start", "-1$period", "-aPNG", "-i", "-z", + "--alt-y-grid", "-w 800", "-h 400", "-l 0", "-u 10000000", "-r", + "--color", "SHADEA#FFFFFF", + "--color", "SHADEB#FFFFFF", + "--color", "BACK#FFFFFF", + "-t $device load per $period", + "DEF:received=$rrdfile:received:AVERAGE", + "DEF:transmitted=$rrdfile:transmitted:AVERAGE", + + "LINE2:received#FF0000:received load\\j", + "LINE1:transmitted#0000FF:transmitted load\\j"); + + $ERROR = RRDs::error; + print "Error in RRD::graph for network $device: $ERROR\n" if $ERROR; + } +} + +sub updatenetdata { + open NETDEV, "/proc/net/dev"; + while () { + chomp; + s/^\s+//; # remove left side whitespaces + /:.+/ or next; # if input line contains ':' else continue + next if /^lo:\s/; # continue if input line starts with 'lo:' + + @tokens1 = split /:/; + @tokens2 = split(/\s+/, $tokens1[1]); + + $device = $tokens1[0]; + $received = $tokens2[0]; + $transmitted = $tokens2[8]; + + #print "$device, $received, $transmitted \n"; + + if ( ! -e "$rrdlog/network-$device.rrd") { + RRDs::create ("$rrdlog/network-$device.rrd", "--step=300", + "DS:received:COUNTER:600:0:U", + "DS:transmitted:COUNTER:600:0:U", + + "RRA:AVERAGE:0.5:1:576", + "RRA:AVERAGE:0.5:6:672", + "RRA:AVERAGE:0.5:24:732", + "RRA:AVERAGE:0.5:144:1460"); + $ERROR = RRDs::error; + print "Error in RRD::create for device $device: $ERROR\n" if $ERROR; + } + + RRDs::update ("$rrdlog/network-$device.rrd", + "-t", "received:transmitted", + "N:$received:$transmitted"); + $ERROR = RRDs::error; + print "Error in RRD::update for net: $ERROR\n" if $ERROR; + } + close NETDEV +} diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py new file mode 100755 index 00000000..73982971 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_cpu_details.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +from XmlHandler import ResponseXml +import Utils + +def createMemData(file, step): + rs = ResponseXml() + command = ["rrdtool", "create", file, "--step=%s" % step, + "DS:user:COUNTER:600:0:U", + "DS:system:COUNTER:600:0:U", + "DS:idle:COUNTER:600:0:U", + "RRA:AVERAGE:0.5:1:576", + "RRA:AVERAGE:0.5:6:672", + "RRA:AVERAGE:0.5:24:732", + "RRA:AVERAGE:0.5:144:1460"] + + rv = Utils.runCommand(command, output=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to create RRD file for cpu usages %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return None + +def updateMemData(file): + rs = ResponseXml() + user = None + system = None + idle = None + for line in open("/proc/stat").readlines(): + if line.startswith("cpu"): + cpudetails = line.split() + if "cpu" == cpudetails[0]: + user = cpudetails[1] + system = cpudetails[3] + idle = cpudetails[4] + break + + if None == user: + Utils.log("failed to fetch cpu details from /proc/stat") + rs.appendTagRoute("status.code", "-1") + rs.appendTagRoute("status.message", "failed to fetch cpu details") + return rs.toxml() + + command = ["rrdtool", "update", file, "-t", "user:system:idle", + "N:%s:%s:%s" % (user, system, idle)] + rv = Utils.runCommand(command, output=True, root=True) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message = "Error: [%s]" % (error) + Utils.log("failed to update cpu usage into rrd file %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return None + + +def main(): + cpuRrdFile = "/var/lib/rrd/cpu.rrd" + if not os.path.exists(cpuRrdFile): + status = createMemData(cpuRrdFile, 100) + if status: + print status + status = updateMemData(cpuRrdFile) + if status: + print status + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py new file mode 100755 index 00000000..fe4fcce6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/rrd_update_memory_details.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . +import os +import sys +from XmlHandler import ResponseXml +import Utils + +def createMemData(file, step): + rs = ResponseXml() + command = ["rrdtool", "create", file, "--step=%s" % step, + "DS:memused:ABSOLUTE:600:0:U", + "DS:memfree:ABSOLUTE:600:0:U", + "DS:memcache:ABSOLUTE:600:0:U", + "DS:swapused:ABSOLUTE:600:0:U", + "DS:swapfree:ABSOLUTE:600:0:U", + "RRA:AVERAGE:0.5:1:576", + "RRA:AVERAGE:0.5:6:672", + "RRA:AVERAGE:0.5:24:732", + "RRA:AVERAGE:0.5:144:1460"] + + rv = Utils.runCommand(command, output=True, root=True) + message = Utils.stripEmptyLines(rv["Stdout"]) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to create RRD file for memory usages %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return None + +def updateMemData(file): + rs = ResponseXml() + command = ["free", "-b", "-o"] + rv = Utils.runCommand(command, output=True, root=True) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log("failed to retrieve memory details") + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + + message = rv["Stdout"].split() + command = ["rrdtool", "update", file, "-t", "memused:memfree:memcache:swapused:swapfree", + "N:%s:%s:%s:%s:%s" % (message[8], message[9], message[12], message[14], message[15])] + rv = Utils.runCommand(command, output=True, root=True) + if rv["Stderr"]: + error = Utils.stripEmptyLines(rv["Stderr"]) + message += "Error: [%s]" % (error) + Utils.log(syslog.LOG_ERR, "failed to update memory usage into rrd file %s" % file) + rs.appendTagRoute("status.code", rv["Status"]) + rs.appendTagRoute("status.message", message) + return rs.toxml() + return None + + +def main(): + #if len(sys.argv) != 2: + # print >> sys.stderr, "usage: %s " % sys.argv[0] + # sys.exit(-1) + #step = sys.argv[1] + + memRrdFile = "mem.rrd" + if not os.path.exists(memRrdFile): + status = createMemData(memRrdFile, 100) + if status: + print status + status = updateMemData(memRrdFile) + if status: + print status + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py b/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py new file mode 100755 index 00000000..2cc35acc --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/setup_cifs_config.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils + +def main(): + try: + os.mkdir(Globals.GLUSTER_BASE_DIR) + os.mkdir(Globals.VOLUME_CONF_DIR) + os.mkdir(Globals.CIFS_EXPORT_DIR) + os.mkdir(Globals.REEXPORT_DIR) + except OSError, e: + Utils.log("failed to create directory: %s" % str(e)) + sys.exit(1) + try: + fp = open(Globals.VOLUME_SMBCONF_FILE, "w") + fp.close() + except IOError, e: + Utils.log("Failed to create file %s: %s" % (Globals.VOLUME_SMBCONF_FILE, str(e))) + sys.exit(2) + try: + os.rename(Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE) + except IOError, e: + Utils.log("Ignoring rename %s to %s: %s" % (Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE, str(e))) + try: + fp = open(Globals.SAMBA_CONF_FILE, "w") + fp.write("##\n") + fp.write("## THIS FILE SHOULD NOT BE MODIFIED. IF YOU WANT TO MODIFY SAMBA\n") + fp.write("## CONFIGURATIONS, USE /etc/samba/real.smb.conf FILE\n") + fp.write("##\n") + fp.write("include = %s\n\n" % Globals.REAL_SAMBA_CONF_FILE) + fp.write("## CAUTION: DO NOT REMOVE BELOW LINE. REMOVAL OF THE LINE DISABLES\n") + fp.write("## CIFS REEXPORT OF GLUSTER VOLUMES\n") + fp.write("include = %s\n" % Globals.VOLUME_SMBCONF_FILE) + fp.close() + except IOError, e: + Utils.log("Failed to create samba configuration file %s: %s" % (Globals.SAMBA_CONF_FILE, str(e))) + sys.exit(3) + try: + fp = open(Globals.REAL_SAMBA_CONF_FILE, "w") + fp.write("[global]\n") + fp.write("## CAUTION: DO NOT REMOVE BELOW INCLUDE LINE. REMOVAL OF THE LINE\n") + fp.write("## DISABLES SERVER/CIFS HIGH AVAILABILITY\n") + #fp.write("include = %s\n" % Globals.CTDB_SAMBA_CONF_FILE) + fp.write("##\n") + fp.write("socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=131072 SO_RCVBUF=131072\n") + fp.write("read raw = yes\n") + fp.write("server string = %h\n") + fp.write("write raw = yes\n") + fp.write("oplocks = yes\n") + fp.write("max xmit = 131072\n") + fp.write("dead time = 15\n") + fp.write("getwd cache = yes\n") + fp.write("#read size = 131072\n") + fp.write("use sendfile=yes\n") + fp.write("block size = 131072\n") + fp.write("printcap name = /etc/printcap\n") + fp.write("load printers = no\n") + fp.close() + except IOError, e: + Utils.log("Failed to create samba configuration file %s: %s" % (Globals.REAL_SAMBA_CONF_FILE, str(e))) + sys.exit(4) + + + if Utils.runCommand("setsebool -P samba_share_fusefs on") != 0: + Utils.log("failed to set SELinux samba_share_fusefs") + sys.exit(5) + + if Utils.runCommand("service smb restart") != 0: + Utils.log("failed to restart smb service") + sys.exit(6) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py new file mode 100755 index 00000000..239216c3 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/start_volume_cifs.py @@ -0,0 +1,41 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils +import VolumeUtils + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + + volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) + cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName) + + if Utils.runCommand("mount -t glusterfs 127.0.0.1:%s %s" % (volumeName, volumeMountDirName)) != 0: + Utils.log("Failed to mount volume %s" % (volumeName)) + sys.exit(1) + if Utils.runCommand("ln -fTs %s %s" % (volumeMountDirName, cifsDirName)) != 0: + Utils.log("Failed to create reexport link %s" % cifsDirName) + sys.exit(2) + if Utils.runCommand("chcon -t samba_share_t %s -h" % cifsDirName) != 0: + Utils.log("Failed to change security context for the link %s" % cifsDirName) + sys.exit(2) + if not VolumeUtils.includeVolume(volumeName): + Utils.log("Failed to include volume for CIFS reexport") + sys.exit(3) + if Utils.runCommand("service smb reload") != 0: + Utils.log("Failed to reload smb service") + sys.exit(4) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py b/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py new file mode 100755 index 00000000..99ac4750 --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/stop_volume_cifs.py @@ -0,0 +1,38 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Globals +import Utils +import VolumeUtils + +def main(): + if len(sys.argv) != 2: + sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + volumeName = sys.argv[1] + + volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) + cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName) + + if not Utils.removeFile(cifsDirName): + Utils.log("Failed to remove reexport link %s" % cifsDirName) + sys.exit(1) + if not VolumeUtils.excludeVolume(volumeName): + Utils.log("Failed to exclude volume for CIFS reexport") + sys.exit(2) + if Utils.runCommand("service smb reload") != 0: + Utils.log("Failed to reload smb service") + sys.exit(3) + if Utils.runCommand("umount %s" % (volumeMountDirName)) != 0: + Utils.log("Failed to unmount volume %s" % (volumeName)) + sys.exit(4) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway/.classpath b/src/com.gluster.storage.management.gateway/.classpath new file mode 100644 index 00000000..107e139d --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/.project b/src/com.gluster.storage.management.gateway/.project new file mode 100644 index 00000000..3e4dc06a --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.project @@ -0,0 +1,41 @@ + + + com.gluster.storage.management.gateway + + + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.jdt.core.javanature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/src/com.gluster.storage.management.gateway/.settings/.jsdtscope b/src/com.gluster.storage.management.gateway/.settings/.jsdtscope new file mode 100644 index 00000000..3a28de0c --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..476db350 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Wed Dec 29 14:57:23 IST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.ltk.core.refactoring.prefs b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 00000000..5d9c71b6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.component b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.component new file mode 100644 index 00000000..3d5a50bf --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.component @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.project.facet.core.xml b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 00000000..8f960f27 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.container b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 00000000..3bd5d0a4 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.container @@ -0,0 +1 @@ +org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.name b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 00000000..05bd71b6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.ws.service.policy.prefs b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.ws.service.policy.prefs new file mode 100644 index 00000000..e5ca6272 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/.settings/org.eclipse.wst.ws.service.policy.prefs @@ -0,0 +1,3 @@ +#Mon Jan 31 15:29:36 IST 2011 +eclipse.preferences.version=1 +org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/src/com.gluster.storage.management.gateway/WebContent/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.gateway/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/antlr-2.7.6.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/antlr-2.7.6.jar new file mode 100644 index 00000000..3702b645 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/antlr-2.7.6.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/aopalliance-1.0.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/aopalliance-1.0.jar new file mode 100644 index 00000000..578b1a0c Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/aopalliance-1.0.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/asm-3.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/asm-3.1.jar new file mode 100644 index 00000000..8217cae0 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/asm-3.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-collections-3.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-collections-3.1.jar new file mode 100644 index 00000000..41e230fe Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-collections-3.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar new file mode 100644 index 00000000..8758a96b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derby.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derby.jar new file mode 100644 index 00000000..dc8ae8df Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derby.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derbytools.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derbytools.jar new file mode 100644 index 00000000..ca367aae Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/derbytools.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/dom4j-1.6.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/dom4j-1.6.1.jar new file mode 100644 index 00000000..c8c4dbb9 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/dom4j-1.6.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt new file mode 100644 index 00000000..3eddd42f --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt @@ -0,0 +1,87 @@ +Copyright (c) 2006 - 2010 Christian Plattner. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +a.) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +b.) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +c.) Neither the name of Christian Plattner nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +This software includes work that was released under the following license: + +Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich), + Department of Computer Science (http://www.inf.ethz.ch), + Christian Plattner. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +a.) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +b.) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +c.) Neither the name of ETH Zurich nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +The Java implementations of the AES, Blowfish and 3DES ciphers have been +taken (and slightly modified) from the cryptography package released by +"The Legion Of The Bouncy Castle". + +Their license states the following: + +Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle +(http://www.bouncycastle.org) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar new file mode 100644 index 00000000..c0a9ac7b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar new file mode 100644 index 00000000..4c9ac4e9 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate3.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate3.jar new file mode 100644 index 00000000..c1c81141 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/hibernate3.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar new file mode 100644 index 00000000..a3248188 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar new file mode 100644 index 00000000..faf12cf6 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar new file mode 100644 index 00000000..ca612580 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar new file mode 100644 index 00000000..57c2c670 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar new file mode 100644 index 00000000..8f692f4f Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-client-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-client-1.5.jar new file mode 100644 index 00000000..62f790fa Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-client-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-core-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-core-1.5.jar new file mode 100644 index 00000000..92b38466 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-core-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-json-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-json-1.5.jar new file mode 100644 index 00000000..01d8c83b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-json-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar new file mode 100644 index 00000000..1c134f05 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-server-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-server-1.5.jar new file mode 100644 index 00000000..a29d7409 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-server-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-spring-1.5.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-spring-1.5.jar new file mode 100644 index 00000000..c79b4490 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jersey-spring-1.5.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jettison-1.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jettison-1.1.jar new file mode 100644 index 00000000..e4e9c8c3 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jettison-1.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jnlp-servlet.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jnlp-servlet.jar new file mode 100644 index 00000000..23782c02 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jnlp-servlet.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar new file mode 100644 index 00000000..ec8bc818 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jta-1.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jta-1.1.jar new file mode 100644 index 00000000..6d225b76 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/jta-1.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/log4j-1.2.16.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/log4j-1.2.16.jar new file mode 100644 index 00000000..3f9d8476 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/log4j-1.2.16.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/mimepull-1.3.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/mimepull-1.3.jar new file mode 100644 index 00000000..48cc9295 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/mimepull-1.3.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar new file mode 100644 index 00000000..a5d37aa1 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar new file mode 100644 index 00000000..db6f529f Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..7cd3a626 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar new file mode 100644 index 00000000..11fc11b9 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar new file mode 100644 index 00000000..f2e2e927 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar new file mode 100644 index 00000000..bd1367d8 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e46f9eb8 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar new file mode 100644 index 00000000..ea9500d6 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6ef99d8d Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e149290e Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar new file mode 100644 index 00000000..dcd1e4d9 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar new file mode 100644 index 00000000..f7a3b837 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar new file mode 100644 index 00000000..9cea2aef Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..d0550ccd Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar new file mode 100644 index 00000000..1688cf74 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd new file mode 100644 index 00000000..b3aa6af8 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd @@ -0,0 +1,21 @@ +Library-SymbolicName: org.springframework.spring +Library-Version: 3.0.5.RELEASE +Library-Name: Spring Framework +Import-Bundle: + org.springframework.aop;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.asm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.aspects;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.beans;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.context.support;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.core;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.expression;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jdbc;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.jms;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.orm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.oxm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.transaction;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.servlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + org.springframework.web.portlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", + com.springsource.org.aopalliance;version="[1.0.0, 1.0.0]" diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar new file mode 100644 index 00000000..237995c5 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar new file mode 100644 index 00000000..2f52122b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar new file mode 100644 index 00000000..5a2381a0 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6ec9d681 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar new file mode 100644 index 00000000..6d13bd40 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar new file mode 100644 index 00000000..e351ae7b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar new file mode 100644 index 00000000..56222cbf Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar new file mode 100644 index 00000000..d321e76c Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/servlet-api.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/servlet-api.jar new file mode 100644 index 00000000..e5bc672b Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/servlet-api.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar new file mode 100644 index 00000000..f1f4fdd2 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar new file mode 100644 index 00000000..78818fc5 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar new file mode 100644 index 00000000..a8077d5d Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar new file mode 100644 index 00000000..26611b55 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar differ diff --git a/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/web.xml b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/web.xml new file mode 100644 index 00000000..631788ff --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/WEB-INF/web.xml @@ -0,0 +1,73 @@ + + + glustermg + + index.html + index.htm + index.jsp + default.html + default.htm + default.jsp + + + contextConfigLocation + + classpath:spring/gluster-server-security.xml + classpath:spring/gluster-server-base.xml + + + + org.springframework.web.context.ContextLoaderListener + + + org.springframework.web.context.request.RequestContextListener + + + gluster-resources-1.0 + com.sun.jersey.spi.spring.container.servlet.SpringServlet + + com.sun.jersey.config.property.packages + com.gluster.storage.management.gateway.resources.v1_0 + + + com.sun.jersey.spi.container.ResourceFilters + com.gluster.storage.management.gateway.filters.GlusterResourceFilterFactory + + 1 + + + gluster-resources-1.0 + /1.0/* + + + JnlpDownloadServlet + jnlp.sample.servlet.JnlpDownloadServlet + + + JnlpDownloadServlet + *.jnlp + + + JnlpDownloadServlet + *.jar + + + springSecurityFilterChain + + org.springframework.web.filter.DelegatingFilterProxy + + + + springSecurityFilterChain + /* + + + + Gluster Management Gateway + /* + + + CONFIDENTIAL + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/0-version.sql b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/0-version.sql new file mode 100644 index 00000000..4c3d81d1 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/0-version.sql @@ -0,0 +1,2 @@ +create table version (version varchar(16) not null primary key); +insert into version(version) values('1.0.0'); \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/1-security-schema.sql b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/1-security-schema.sql new file mode 100644 index 00000000..fdde5823 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/1-security-schema.sql @@ -0,0 +1,26 @@ +create table users( + username varchar(50) not null primary key, + password varchar(50) not null, + enabled smallint not null + ); + + create table authorities ( + username varchar(50) not null, + authority varchar(50) not null, + constraint fk_authorities_users foreign key(username) references users(username)); + create unique index ix_auth_username on authorities (username,authority); + +create table groups ( + id bigint generated by default as identity(start with 0) primary key, + group_name varchar(50) not null); + +create table group_authorities ( + group_id bigint not null, + authority varchar(50) not null, + constraint fk_group_authorities_group foreign key(group_id) references groups(id)); + +create table group_members ( + id bigint generated by default as identity(start with 0) primary key, + username varchar(50) not null, + group_id bigint not null, + constraint fk_group_members_group foreign key(group_id) references groups(id)); diff --git a/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql new file mode 100644 index 00000000..35ccf965 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql @@ -0,0 +1,21 @@ +-- Create users +insert into users(username, password, enabled) values ('gluster','gluster',1); +insert into users(username, password, enabled) values ('guest','guest',1); + +-- Assign authorities to users (to be removed after implementing user group functionality) +insert into authorities(username,authority) values ('gluster','ROLE_USER'); +insert into authorities(username,authority) values ('gluster','ROLE_ADMIN'); +insert into authorities(username,authority) values ('guest','ROLE_USER'); + +-- Create user groups +insert into groups(group_name) values ('Users'); +insert into groups(group_name) values ('Administrators'); + +-- Add authorities to groups (functionality not yet implemented in code) +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Users'; +insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Administrators'; +insert into group_authorities(group_id, authority) select id,'ROLE_ADMIN' from groups where group_name='Administrators'; + +-- Assign group members +insert into group_members(group_id, username) select id,'guest' from groups where group_name='Users'; +insert into group_members(group_id, username) select id,'gluster' from groups where group_name='Administrators'; \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/3-cluster-servers.sql b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/3-cluster-servers.sql new file mode 100644 index 00000000..17ca62d2 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/data/scripts/1.0.0/3-cluster-servers.sql @@ -0,0 +1,16 @@ +create table cluster_info ( + id bigint generated by default as identity, + name varchar(255), + primary key (id)); + +create unique index ix_cluster_name on cluster_info (name); + +create table server_info ( + id bigint generated by default as identity, + name varchar(255), + cluster_id bigint, + primary key (id)); + +create unique index ix_cluster_server on server_info (name, cluster_id); + +alter table server_info add constraint FK_CLUSTER_ID foreign key (cluster_id) references cluster_info(id); \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/WebContent/index.html b/src/com.gluster.storage.management.gateway/WebContent/index.html new file mode 100644 index 00000000..4c90162a --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/index.html @@ -0,0 +1,8 @@ + + +Gluster Management Console + + +TODO: Identify the client's platform-browser and invoke appropriate JNLP URL. + + diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py new file mode 100644 index 00000000..f8a07c25 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py @@ -0,0 +1,123 @@ +# Copyright (C) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +MULTICAST_GROUP = '224.224.1.1' +MULTICAST_PORT = 5353 +GLUSTER_PLATFORM_VERSION = "3.2" + +## System configuration constants +SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" +DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" + +FSTAB_FILE = "/etc/fstab" +NFS_EXPORTS_FILE = "/etc/exports" +SAMBA_CONF_FILE = "/etc/samba/smb.conf" +TIMEZONE_FILE = "/etc/timezone" +ZONEINFO_DIR = "/usr/share/zoneinfo" +LOCALTIME_FILE = "/etc/localtime" +KERBEROS_CONF_FILE = "/etc/krb5.conf" +NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" +NTP_CONF_FILE = "/etc/ntp.conf" +MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" +SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" +RESOLV_CONF_FILE = "/etc/resolv.conf" +DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" +LIVE_MODE_FILE = "/etc/live" +ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" + +DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" +DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" +## + +## Base constants +MAX_PARTITION_SIZE = 16777216 # 16 TB +OS_PARTITION_SIZE = 4000 # 4 GB +SESSION_TIMEOUT = 1800 # 30 minutes +SERVER_AGENT_PORT = 50000 + +BOOT_PARTITION_LABEL = "GLUSTEROS" +DATA_PARTITION_LABEL = "GLUSTERDATA" +VOLUME_USER_DESCRIPTION = "Gluster Volume User" +SERVER_AGENT_RUN_USERNAME = "gluster" +INSTALLER_SERVER_NAME = "$installer$" + +GLUSTER_BASE_DIR = "/etc/glustermg" +GLUSTER_LUN_DIR = "/data" +REEXPORT_DIR = "/reexport" +NFS_EXPORT_DIR = "/nfs" +CIFS_EXPORT_DIR = "/cifs" +WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" +UPDATES_DIR = "/UPDATES" +TRANSPORT_HOME_DIR = "/transport" +GLUSTERFS_LOG_DIR = "/var/log/glusterfs" +LOG_DIR = "/var/log/glustermg" + +GLUSTER_UPDATES_FILE = "updates.xml" +INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" +INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" +LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" +PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" +## + +## Derived constants +GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" +GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" +VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" +SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" +DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" +INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME + +GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" +GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" +GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" +GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" +GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" +TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" +SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" +SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" +GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" +GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" + +VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" + +GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" +INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" +INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" +INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" + +SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" + +GENERAL_LOG_FILE = LOG_DIR + "/general.log" +INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" +PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log" +SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" +TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" +## + + +## Global variables +## TODO: These should be removed +DOWNLOAD_GLUSTER_UPDATE_PROCESS = None +DOWNLOAD_GLUSTER_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None +DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None +REQUEST_MAP = {} +VERSION_DICTONARY = {} +## + +AWS_WEB_SERVICE_URL = "http://169.254.169.254/latest" +REAL_SAMBA_CONF_FILE = "/etc/samba/real.smb.conf" diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/Protocol.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/Protocol.py new file mode 100644 index 00000000..ff073593 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/Protocol.py @@ -0,0 +1,438 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc.strip() + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTextNode(self, text): + if not self._domObj: + return False + if not text: + return False + return self._domObj.createTextNode(str(text)) + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def getAttribute(self, attributeName): + if not attributeName: + return None + try: + return self.getElementsByTagName("command")[0].getAttribute(attributeName) + except IndexError: + return False + + def setAttribute(self, attributeName, attributeValue): + if not (attributeName and attributeValue): + return None + try: + return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue) + except IndexError: + return False + + def getRequestCommand(self): + return self.getAttribute("request") + + def getResponseCommand(self): + return self.getAttribute("response") + + def getResponseCode(self): + return self.getAttribute("response-code") + + def getMessageId(self): + return self.getAttribute("id") + + def getVersion(self): + return self.getAttribute("version") + + def getRequestAction(self): + return self.getAttribute("action") + + def setVersion(self, value): + return self.setAttribute("version", value) + + def setRequestAction(self, value): + return self.setAttribute("action", value) + + def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + commandTag = self._domObj.createElement("command") + commandTag.setAttribute("response", command) + commandTag.setAttribute("response-code", responseCode) + commandTag.setAttribute("id", id) + commandTag.setAttribute("version", version) + return commandTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + +class ResponseXml(XDOM): + _commandTag = None + def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + XDOM.__init__(self) + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + + def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): + if command and responseCode and id: + self._commandTag = self.createCommandTag(command, responseCode, id, version) + self._domObj.appendChild(self._commandTag) + return True + return False + + def append(self, tagName, tagValue=None): + if not self._commandTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._commandTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._commandTag: + return False + self._commandTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._commandTag: + return False + if not tagRoute: + return False + + parentTagE = self._commandTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def appendTagRouteOld(self, tagRoute, value=None): + if not tagRoute: + return False + if not self._commandTag: + return False + + tmpTagRoute = "" + previousTagE = self._commandTag + tagE = None + for tagName in tagRoute.split("."): + if not tmpTagRoute: + tagE = self.getElementsByTagRoute("command." + tagName) + else: + tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName) + if not tagE: + break + if len(tagE) != 1: + return False + previousTagE = tagE[0] + if not tmpTagRoute: + tmpTagRoute = tagName + else: + tmpTagRoute = tmpTagRoute + "." + tagName + + if tmpTagRoute == tagRoute: + return False + newTagRoute = tagRoute[len(tmpTagRoute):] + if newTagRoute[0] == '.': + newTagRoute = newTagRoute[1:] + + if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE: + return False + previousTagE.appendChild(self.createTagRoute(newTagRoute, value)) + return True +##--end of ResponseXml + +def test(): + #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume") + requestStr = ''' + +movies1 +cluster mirror +512000 +zresearch +192.168.20.* +192.168.30.* + +no + + +no + + +no + + +''' + + requestXml = RequestXml(requestStr) + print requestXml.getAttribute("") + +def test1(): + rs = ResponseXml("create-volume", "OK", "xyz") + rs.appendTagRoute("volume.detail.name", "music") + print rs.toprettyxml() + rs.append("volume", "data") + print rs.toprettyxml() + rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1") + print rs.toprettyxml() + print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::") + print rs.toprettyxml() + + print rs.getTextByTagRoute("command.volume.detail") + +def test2(): + rs = ResponseXml("download-volume-logs", "OK", "xyz") + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE1")) + te.appendChild(rs.createTag("description", "my device one")) + rs.appendTag(te) + + te = rs.createTag("interface", None) + te.appendChild(rs.createTag("device", "DEVICE2")) + te.appendChild(rs.createTag("description", "my device two")) + rs.appendTag(te) + print rs.toprettyxml() + diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/Utils.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/Utils.py new file mode 100644 index 00000000..3408c14a --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/Utils.py @@ -0,0 +1,1059 @@ +# Copyright (c) 2010 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import os +import re +import socket +import struct +import syslog +import subprocess +#import spwd +import time +#import uuid +import tempfile +import grp +import pwd +import inspect +from datetime import datetime +import urllib + +import Globals +import Protocol + +RUN_COMMAND_ERROR = -1024 +LOG_SYSLOG = 1 +SYSLOG_REQUIRED = False +LOG_FILE_NAME = None +LOG_FILE_OBJ = None + + +def _getLogCode(priority): + if syslog.LOG_EMERG == priority: + return "M" + elif syslog.LOG_ALERT == priority: + return "A" + elif syslog.LOG_CRIT == priority: + return "C" + elif syslog.LOG_ERR == priority: + return "E" + elif syslog.LOG_WARNING == priority: + return "W" + elif syslog.LOG_NOTICE == priority: + return "N" + elif syslog.LOG_INFO == priority: + return "I" + elif syslog.LOG_DEBUG == priority: + return "D" + else: # UNKNOWN + return "X" + + +def setLogFile(fileName): + global LOG_FILE_NAME + + if fileName: + LOG_FILE_NAME = fileName + return True + return False + + +def closeLog(): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if SYSLOG_REQUIRED: + syslog.closelog() + SYSLOG_REQUIRED = False + return True + + if LOG_FILE_OBJ: + try: + LOG_FILE_OBJ.close() + LOG_FILE_OBJ = None + except IOError, e: + sys.stderr.write("Failed to close file: %s\n" % e) + return False + return True + + +def openLog(fileName=None): + global LOG_FILE_NAME + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + if fileName == LOG_SYSLOG: + syslog.openlog(os.path.basename(sys.argv[0])) + SYSLOG_REQUIRED = True + return True + + if fileName: + LOG_FILE_NAME = fileName + + if not LOG_FILE_NAME: + return False + + closeLog() + + try: + LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") + except IOError, e: + sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) + return False + return True + +def record(priority, message=None): + global LOG_FILE_OBJ + global SYSLOG_REQUIRED + + stack = inspect.stack()[1] + if stack[3] == "": + prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3]) + else: + prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3]) + + if type(priority) == type("") or type(priority) == type(u""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + + if SYSLOG_REQUIRED: + syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage)) + return + + fp = sys.stderr + if LOG_FILE_OBJ: + fp = LOG_FILE_OBJ + + fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage)) + if logMessage[-1] != '\n': + fp.write("\n") + fp.flush() + return + + +def trace(message): + if message: + log(syslog.LOG_DEBUG, message) + + +def isString(value): + return (type(value) == type("") or type(value) == type(u"")) + + +def getTempFileName(): + filedesc, filename = tempfile.mkstemp(prefix="GSP_") + os.close(filedesc) + return filename + + +def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, + shell=False, root=None): + log("runCommandBG(): Trying to execute command [%s]" % command) + + if shell: + if not isString(command): + return None + else: + if isString(command): + command = command.split() + + if root == True: + if shell: + command = "sudo " + command + else: + command = ['sudo'] + command + elif isString(root): + if shell: + command = "sudo -u " + root + " " + command + else: + command = ['sudo', '-u', root] + command + + if not stdinFileObj: + stdinFileObj=subprocess.PIPE + if not stdoutFileObj: + stdoutFileObj=subprocess.PIPE + if not stderrFileObj: + stderrFileObj=subprocess.PIPE + + try: + process = subprocess.Popen(command, + bufsize=-1, + stdin=stdinFileObj, + stdout=stdoutFileObj, + stderr=stderrFileObj, + shell=shell) + return process + except OSError, e: + log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) + return None + + +def runCommand(command, + input='', output=False, + shell=False, root=None): + rv = {} + rv["Status"] = RUN_COMMAND_ERROR + rv["Stdout"] = None + rv["Stderr"] = None + + try: + stdinFileName = getTempFileName() + stdinFileObj = open(stdinFileName, "w") + stdinFileObj.write(input) + stdinFileObj.close() + stdinFileObj = open(stdinFileName, "r") + + stdoutFileName = getTempFileName() + stdoutFileObj = open(stdoutFileName, "w") + + stderrFileName = getTempFileName() + stderrFileObj = open(stderrFileName, "w") + except IOError, e: + log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) + if output: + return rv + return rv["Status"] + + stdoutContent = None + stderrContent = None + + process = runCommandBG(command, + stdinFileObj=stdinFileObj, + stdoutFileObj=stdoutFileObj, + stderrFileObj=stderrFileObj, + shell=shell, root=root) + if process: + rv['Status'] = process.wait() + rv['Stdout'] = open(stdoutFileName).read() + rv['Stderr'] = open(stderrFileName).read() + + os.remove(stdinFileName) + os.remove(stdoutFileName) + os.remove(stderrFileName) + + log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) + + if output: + return rv + return rv["Status"] + + +def runCommandFG(command, stdout=False, stderr=False, + shell=False, root=None): + if stdout or stderr: + output = True + else: + output = False + return runCommand(command, output=output, shell=shell, root=root) + + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + + +def computeHostName(hostName): + if not hostName: + return False + + hostPrefix = "" + for i in range(len(hostName), 0, -1): + pos = i - 1 + if hostName[pos].isdigit(): + continue + break + hostPrefix = hostName[:pos+1] + try: + hostIndex = int(hostName[pos+1:]) + except ValueError: + hostIndex = 0 + # TODO: Check the availablity of the (server) name + return "%s%s" % (hostPrefix, hostIndex + 1) + + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + + +def getDownloadStatus(fileName): + try: + lines = [line for line in open(fileName) + if "saved" in line or "%" in line] + except IOError: + return 0 + if not lines: + return 0 + if "saved" in lines[-1]: + return 100 + return lines[-1].split("%")[0].split()[-1] + + +def getMeminfo(): + """-> dict of data from meminfo (str:int). + Values are in kilobytes. + """ + import re + re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB' ) + result = {} + for line in open('/proc/meminfo'): + match = re_parser.match(line) + if not match: + continue # skip lines that don't parse + key, value = match.groups(['key', 'value']) + result[key] = int(value) + result['MemUsed'] = (result['MemTotal'] - result['MemFree']) + return result + + +def getCpuUsage(): + """-> dict of cpuid : (usertime, nicetime, systemtime, idletime) + cpuid "cpu" means the total for all CPUs. + cpuid "cpuN" means the value for CPU N. + """ + wanted_records = [line for line in open('/proc/stat') if + line.startswith('cpu')] + result = {} + for cpuline in wanted_records: + fields = cpuline.split()[:5] + data = map(int, fields[1:]) + result[fields[0]] = tuple(data) + return result + +def _getCpuStatList(): + try: + fp = open("/proc/stat") + cpuStatList = map(float, fp.readline().split()[1:]) + fp.close() + return cpuStatList + except IOError, e: + Utils.log("Failed to open /proc/stat: %s" % str(e)) + return None + +def getCpuUsageAvg(): + st1 = _getCpuStatList() + time.sleep(2) + st2 = _getCpuStatList() + if not (st1 and st2): + return None + delta = [st2[i] - st1[i] for i in range(len(st1))] + cpuPercent = sum(delta[:3]) / delta[3] * 100.0 + return str('%.4f' % cpuPercent) + +def getLoadavg(): + try: + loadavgstr = open('/proc/loadavg', 'r').readline().strip() + except IOError: + syslog.syslog(syslog.LOG_ERR, "failed to find cpu load") + return None + + data = map(float, loadavgstr.split()[1:]) + # returns 1 minute load average + return data[0] + + +def getInfinibandPortStatus(): + + """ Check for availability of infiniband port + and return which port is active in a key pair value + """ + + # Check for existence of infiniband ports + value = os.popen ("ls /sys/class/infiniband").readline().strip() + + if not value: + return None + + portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split() + + portkeys = {} + + for port in portlist: + value = os.popen ("cat %s/state" % + port.strip()).readline().split(':')[1].strip() + portkeys[port.strip()] = value + + return portkeys + + +def getServerCount(): + try: + return int(open(Globals.SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE) + return 1 + + +def setServerCount(count): + try: + open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.SERVER_COUNT_FILE) + return False + + +def getInstalledServerCount(): + try: + return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip()) + except IOError: + log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + except ValueError: + log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return 1 + + +def setInstalledServerCount(count): + try: + open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count) + return True + except IOError: + log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) + return False + + +def getLastInstalledServerIpList(): + ipList = {} + networkDom = Protocol.XDOM() + if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE): + log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE) + for tagE in networkDom.getElementsByTagRoute("server.interface"): + interfaceDom = Protocol.XDOM() + interfaceDom.setDomObj(tagE) + ipAddress = interfaceDom.getTextByTagRoute("ipaddr") + if ipAddress: + ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress + return ipList + + +def getFreeIpAddress(device=None): + serverCount = getServerCount() + installedServerCount = getInstalledServerCount() + if serverCount == installedServerCount: + return None + + availableServerCount = serverCount - installedServerCount + ipList = getLastInstalledServerIpList() + + if not ipList: + return None + + if device: + if device not in ipList.keys(): + return None + deviceIpAddress = ipList[device] + else: + deviceIpAddress = ipList.values()[0] + ipNumber = IP2Number(deviceIpAddress) + + for i in range((ipNumber + availableServerCount), ipNumber, -1): + ipAddress = Number2IP(i) + if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0: + return ipAddress + return None + + +def getPasswordHash(userName): + try: + #return spwd.getspnam(userName).sp_pwd + return "Not implimented" + except KeyError: + return None + + +def getTransactionKey(): + try: + tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',') + except IOError: + return None, None + return tokens + + +def generateSignature(): + #return str(uuid.uuid4()) + ('--%f' % time.time()) + return ('--%f' % time.time()) + + +def getSignature(): + try: + return open(Globals.SIGNATURE_FILE).read().strip() + except IOError: + log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE) + return False + + +def storeSignature(signature, fileName=Globals.SIGNATURE_FILE): + try: + open(fileName, "w").write(signature + "\n") + except IOError: + log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName)) + return False + return True + + +def isUserExist(userName): + try: + grp.getgrnam(userName).gr_gid + return True + except KeyError: + pass + try: + pwd.getpwnam(userName).pw_uid + return True + except KeyError: + pass + return False + + +def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE): + userInfo = {} + userInfo["UserId"] = None + userInfo["Password"] = None + try: + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "GSN_ID": + userInfo["UserId"] = v + if k.upper() == "GSN_PASSWORD": + userInfo["Password"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return userInfo + + +def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE): + try: + fp = open(fileName, "w") + fp.write("GSN_ID=%s\n" % userInfo["UserId"]) + fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"]) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE): + versionInfo = {} + versionInfo["Version"] = None + versionInfo["Update"] = None + try: + lines = open(Globals.GLUSTER_VERSION_FILE).readlines() + for line in open(fileName): + line = line.strip() + k = line[:line.index("=")] + v = line[line.index("=") + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "VERSION": + versionInfo["Version"] = v + if k.upper() == "UPDATE": + versionInfo["Update"] = v + except IOError, e: + log("Failed to read file %s: %s" % (fileName, e)) + return versionInfo + + +def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE): + if isString(versionInfo): + tokens = versionInfo.strip().split(".") + if len(tokens) < 2: + log("Invalid version format %s. Expecting .." % versionInfo) + return False + version = ".".join(tokens[:2]) + update = ".".join(tokens[2:]) + if not update: + update = "0" + else: + version = versionInfo["Version"] + update = versionInfo["Update"] + try: + fp = open(fileName, "w") + fp.write("VERSION=%s\n" % version) + fp.write("UPDATE=%s\n" % update) + fp.close() + return True + except IOError, e: + log("Failed to write file %s: %s" % (fileName, e)) + return False + + +def getGlusterUpdateDom(serverVersion): + errorMessage = "" + updateInfoDom = None + try: + baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip() + except IOError, e: + log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e)) + errorMessage = "Failed to read update site file" + return updateInfoDom, errorMessage + + try: + url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE) + connection = urllib.urlopen(url) + if connection.getcode() != 200: + connection.close() + errorMessage = "Error received from server to open URL %s" % url + return updateInfoDom, errorMessage + updateInfoString = connection.read() + connection.close() + except IOError, e: + log("Failed to get update information from URL %s: %s" % (url, e)) + errorMessage = "Error getting update information" + return updateInfoDom, errorMessage + + updateInfoDom = Protocol.XDOM() + if not updateInfoDom.parseString(updateInfoString): + log("XML parse error on update information content [%s]" % updateInfoString) + errorMessage = "Parse error on update information" + updateInfoDom = None + return updateInfoDom, errorMessage + + +def removeFile(fileName, root=False): + if root: + if runCommand("rm %s" % fileName, root=True) == 0: + return True + return False + try: + os.remove(fileName) + return True + except OSError, e: + log("Failed to remove file %s: %s" % (fileName, e)) + return False + + +def isLiveMode(): + return os.path.exists(Globals.LIVE_MODE_FILE) + +def convertKbToMb(kb): + return kb / 1024.0 + + +def getIPIndex(indexFile): + try: + fp = open(indexFile) + line = fp.readline() + fp.close() + index = int(line) + except IOError: + index = 0 + except ValueError: + index = False + return index + +def setIPIndex(index, indexFile): + try: + fp = open(indexFile, "w") + fp.write(str(index)) + fp.close() + except IOError: + return False + return True + +def IP2Number(ipString): + try: + return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) + except socket.error: + return None + except TypeError: + return None + except struct.error: + return None + +def Number2IP(number): + try: + return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) + except socket.error: + return None + except AttributeError: + return None + except ValueError: + return None + +def hasEntryFoundInFile(searchString, dnsEntryFileName): + try: + addServerEntryList = open(dnsEntryFileName).read().split() + except IOError: + return None + if searchString in addServerEntryList: + return True + return False + + +def computeIpAddress(ipAddress, startIp, endIp): + startIpNumber = IP2Number(startIp) + endIpNumber = IP2Number(endIp) + if not ipAddress: + return startIp + nextIpNumber = IP2Number(ipAddress) + while True: + nextIpNumber = nextIpNumber + 1 + ipAddress = Number2IP(nextIpNumber) + rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) + if type(rv) == type(True): + return False + if rv != 0: + break + + if nextIpNumber >= startIpNumber and nextIpNumber <= endIpNumber: + return ipAddress + + nextIpNumber = IP2Number(startIp) + while True: + ipAddress = Number2IP(nextIpNumber) + nextIpNumber = nextIpNumber + 1 + rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) + if type(rv) == type(True): + return False + if rv != 0: + break + + if IP2Number(ipAddress) >= startIpNumber and IP2Number(ipAddress) <= endIpNumber: + return ipAddress + return False + + +def setHostNameAndIp(hostName, ipAddress, lastAddServerDetailFile): + try: + fp = open(lastAddServerDetailFile, "w") + fp.write("HOSTNAME=" + hostName + "\n") + fp.write("IPADDRESS=" + ipAddress); + fp.close() + except IOError: + return False + return True + +def getPort(): + try: + fd = open(Globals.PORT_FILE, "r") + portString = fd.readline() + fd.close() + port = int(portString) + except IOError: + port = Globals.DEFAULT_PORT - 2 + except ValueError: + port = Globals.DEFAULT_PORT - 2 + return port + +def setPort(port): + try: + fd = open(Globals.PORT_FILE, "w") + fd.write(str(port)) + fd.close() + except IOError: + return False + return True + +def getServerAgentCredentials(): + try: + lines = open(Globals.SERVERAGENT_AUTH_FILE).readlines() + except IOError: + return None,None + + userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "AGENT_ID": + userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return userName, password + +def getGatewayAgentCredentials(): + try: + lines = open(Globals.GATEWAYAGENT_AUTH_FILE).readlines() + except IOError: + return None + + #userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + #if k.upper() == "AGENT_ID": + # userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return password + +def getWebAgentCredentials(): + try: + lines = open(Globals.WEBAGENT_AUTH_FILE).readlines() + except IOError: + return None,None + + userName = None + password = None + + for l in lines: + if l[-1] == '\n': + l = l[:-1] + k = l[:l.index('=')] + v = l[l.index('=') + 1:] + if v[0] == "'" or v[0] == '"': + v = v[1:] + if v[-1] == "'" or v[-1] == '"': + v = v[:-1] + if k.upper() == "AGENT_ID": + userName = v + if k.upper() == "AGENT_PASSWORD": + password = v + + return userName, password + +def daemonize(): + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + return False + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file("/dev/null", 'r') + so = file("/dev/null", 'a+') + se = file("/dev/null", 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + return True + +def getFreeIpAddress(): + startRange, endRange = getStoragePoolInfo() + if not (startRange and endRange): + return None + + startIpNumber = IP2Number(startRange) + endIpNumber = IP2Number(endRange) + + for ipNumber in range(endIpNumber, startIpNumber, -1): + rv = runCommandFG(["ping", "-qnc", "1", Number2IP(ipNumber)]) + if type(rv) == type(True): + return None + if rv != 0: + return Number2IP(ipNumber) + return None + +def getDhcpServerStatus(): + status = runCommandFG(["sudo", "service", "dnsmasq", " status"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def startDhcpServer(): + status = runCommandFG(["sudo", "service", "dnsmasq", " start"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def stopDhcpServer(): + status = runCommandFG(["sudo", "service", "dnsmasq", " stop"]) + if type(status) == type(True) or 0 != status: + return False + return True + +def getStoragePoolInfo(): + startRange = None + endRange = None + try: + for line in open(Globals.GLUSTER_SERVER_POOL_FILE): + tokens = line.split("=") + if tokens[0] == "STARTRANGE": + startRange = tokens[1].strip() + if tokens[0] == "ENDRANGE": + endRange = tokens[1].strip() + except IOError: + log(syslog.LOG_ERR, "unable to read %s file" % Globals.GLUSTER_SERVER_POOL_FILE) + return startRange, endRange + +def configureDnsmasq(serverIpAddress, dhcpIpAddress): + dnsmasqConfFile = Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf" + serverPortString = "68" + try: + for arg in open("/proc/cmdline").read().strip().split(): + token = arg.split("=") + if token[0] == "dhcp": + serverPortString = token[1] + break + except IOError: + log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") + try: + serverPort = int(serverPortString) + except ValueError: + log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) + serverPort = 68 + + try: + fp = open(dnsmasqConfFile, "w") + fp.write("no-hosts\n") + #fp.write("addn-hosts=%s\n" % Globals.GLUSTER_DNS_ENTRIES) + fp.write("bind-interfaces\n") + fp.write("except-interface=lo\n") + fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) + fp.write("dhcp-lease-max=1\n") + #fp.write("dhcp-option=option:router,%s\n" % serverIp) + #fp.write("dhcp-option=option:ntp-server,%s\n" % serverIp) + fp.write("dhcp-alternate-port=%s\n" % serverPort) + fp.write("server=%s\n" % serverIpAddress) + fp.write("dhcp-script=/usr/sbin/server-info\n") + fp.close() + except IOError: + log(syslog.LOG_ERR, "unable to write dnsmasq configuration %s" % dnsmasqConfFile) + return False + status = runCommandFG(["sudo", "cp", "-f", Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf", Globals.DNSMASQ_CONF_FILE]) + if type(status) == type(True) or 0 != status: + log(syslog.LOG_ERR, "unable to copy dnsmasq configuration to " + Globals.DNSMASQ_CONF_FILE) + return False + return True + +def configureDhcpServer(serverIpAddress, dhcpIpAddress): + return configureDnsmasq(serverIpAddress, dhcpIpAddress) + +def log(priority, message=None): + if type(priority) == type(""): + logPriority = syslog.LOG_INFO + logMessage = priority + else: + logPriority = priority + logMessage = message + if not logMessage: + return + #if Globals.DEBUG: + # sys.stderr.write(logMessage) + else: + syslog.syslog(logPriority, logMessage) + return + + +def stripEmptyLines(content): + ret = "" + for line in content.split("\n"): + if line.strip() != "": + ret += line + return ret + + +def getDeviceFormatStatusFile(device): + return "/var/tmp/format_%s.status" % device.replace('/', '_') + +def getDeviceFormatLockFile(device): + return "/var/lock/format_%s.lock" % device.replace('/', '_') + +def getDeviceFormatOutputFile(device): + return "/var/tmp/format_%s.out" % device.replace('/', '_') diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/XmlHandler.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/XmlHandler.py new file mode 100644 index 00000000..72164ffb --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/XmlHandler.py @@ -0,0 +1,346 @@ +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import xml +import xml.parsers.expat +import xml.dom.minidom as MDOM +import os +import Globals +import copy +import Utils + +XML_STRING = 0 +XML_FILE = 1 + +class XDOM: + _domObj = None + + def __init__(self): + self._domObj = MDOM.Document() + return + + @classmethod + def getText(self, nodeList): + rc = "" + for node in nodeList: + if node.nodeType == node.TEXT_NODE: + rc = rc + node.data + return rc + + def parseString(self, requestString): + try: + self._domObj = MDOM.parseString(requestString) + except xml.parsers.expat.ExpatError, e: + Utils.log("XML string parse error: %s" % str(e)) + return False + return True + + def parseFile(self, fileName): + try: + self._domObj = MDOM.parse(fileName) + except IOError, e: + Utils.log("error reading file: %s" % str(e)) + return False + except xml.parsers.expat.ExpatError, e: + Utils.log("XML file %s parse error: %s" % (fileName, str(e))) + return False + return True + + def setDomObj(self, dom): + if dom and type(dom) != type([]): + self._domObj = dom + return True + return False + + def createTag(self, tag, text=None): + if not self._domObj: + return None + if tag == None: + return None + + tagE = self._domObj.createElement(str(tag)) + if text: + tagEText = self._domObj.createTextNode(str(text)) + tagE.appendChild(tagEText) + return tagE + + def addTag(self, tag): + if not self._domObj: + return False + if not tag: + return False + + self._domObj.appendChild(tag) + return True + + def createTagRoute(self, tagRoute, text=None): + if not tagRoute: + return False + + tagList = tagRoute.split(".") + tag = None + previousTag = None + for tagName in tagList[:-1]: + newTag = self.createTag(tagName, None) + if not tag: + tag = newTag + previousTag = newTag + continue + previousTag.appendChild(newTag) + previousTag = newTag + + if previousTag: + previousTag.appendChild(self.createTag(tagList[-1], text)) + else: + tag = self.createTag(tagList[-1], text) + return tag + + def appendTagRoute(self, tagRoute, value=None): + if not self._domObj: + return False + if not tagRoute: + return False + + parentTagE = self._domObj + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True + + def setTextByTagRoute(self, tagRoute, tagValue): + if not self._domObj: + return None + + if not tagRoute: + return None + + tagE = self.getElementsByTagRoute(tagRoute) + if not tagE: + return False + + parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) + if not parentTagE: + return False + + parentTagE[0].childNodes.remove(tagE[0]) + parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) + return True + + def getElementsByTagRoute(self, tagRoute): + if not self._domObj: + return None + + if not tagRoute: + return None + + x = None + for tag in tagRoute.split("."): + if x is None: + x = self._domObj.getElementsByTagName(tag) + continue + if x == []: + break + x = x[0].getElementsByTagName(tag) + return x + + def getTextByTagRoute(self, tagRoute): + if not self._domObj: + return None + + x = self.getElementsByTagRoute(tagRoute) + if x: + return self.getText(x[0].childNodes) + return None + + def getElementsByTagName(self, name): + if not self._domObj: + return None + return self._domObj.getElementsByTagName(name) + + def writexml(self, fileName, indent="", addindent="", newl=""): + if not self._domObj: + return None + try: + fp = open(fileName, "w") + self._domObj.writexml(fp, indent, addindent, newl) + fp.close() + return True + except IOError: + return False + + def toString(self, indent=" ", newl="\n", encoding = None): + if not self._domObj: + return None + return self._domObj.toprettyxml(indent, newl, encoding) + + def toxml(self, encoding = None): + if not self._domObj: + return None + return self._domObj.toxml(encoding) + + def toprettyxml(self, indent=" ", newl="\n", encoding = None): + return self.toString(indent, newl, encoding) + + def createResponseTag(self): + responseTag = self._domObj.createElement("response") + return responseTag +##--end of XDOM + +class RequestXml(XDOM): + def __init__(self, requestString, type=None): + if None == requestString: + XDOM.__init__(self) + return + try: + if None == type: + if os.path.isfile(requestString): + self._domObj = MDOM.parse(requestString) + else: + self._domObj = MDOM.parseString(requestString) + elif XML_FILE == type: + self._domObj = MDOM.parse(requestString) + elif XML_STRING == type: + self._domObj = MDOM.parseString(requestString) + except IOError: + XDOM.__init__(self) + except xml.parsers.expat.ExpatError: + XDOM.__init__(self) + +##--end of RequestXML + + +class ResponseXml(XDOM): + _responseTag = None + def __init__(self): + XDOM.__init__(self) + self._responseTag = self.createResponseTag() + self._domObj.appendChild(self._responseTag) + + @classmethod + def errorResponse(self, message): + if not self.responseTag: + return False + self.appendTagRoute("status.code", "-1"); + self.appendTagRoute("status.message", message) + + def append(self, tagName, tagValue=None): + if not self._responseTag: + return False + tag = self.createTag(tagName, tagValue) + if tag: + self._responseTag.appendChild(tag) + return True + return False + + def appendTag(self, tag): + if not tag: + return False + if not self._responseTag: + return False + self._responseTag.appendChild(tag) + return True + + def appendTagRoute(self, tagRoute, value=None): + if not self._responseTag: + return None + if not tagRoute: + return None + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return None + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return None + return newTagE + + def appendTagRouteOld(self, tagRoute, value=None): + if not self._responseTag: + return False + if not tagRoute: + return False + + parentTagE = self._responseTag + + tagNameList = tagRoute.split(".") + newTagRoute = tagNameList.pop(-1) + + for i in range(len(tagNameList), 0, -1): + tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) + if tagE: + parentTagE = tagE[0] + break + newTagRoute = tagNameList[i-1] + "." + newTagRoute + + newTagE = self.createTagRoute(newTagRoute, value) + if not newTagE: + return False + try: + parentTagE.appendChild(newTagE) + except xml.dom.HierarchyRequestErr, e: + Utils.log("error occured. %s" + str(e)) + return False + return True +##--end of ResponseXml + +def test(): + rs = ResponseXml() + rs.appendTagRoute("status.code", "0"); + rs.appendTagRoute("status.message", "SUCCESS") + serverTag = rs.appendTagRoute("server.name", "Server1") + networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface1")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40")) + networkInterfaces.appendChild(networkTag) + networkTag = rs.createTag("networkInterface", None) + networkTag.appendChild(rs.createTag("name", "interface2")) + networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41")) + networkInterfaces.appendChild(networkTag) + print rs.toprettyxml() + +#test() diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/add_user_cifs_all.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/add_user_cifs_all.py new file mode 100755 index 00000000..e4b48658 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/add_user_cifs_all.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Utils + + +defaultUid = 1024000 +cifsUserFile = "/etc/glustermg/.users.cifs" + + +def getLastUid(): + if not os.path.exists(cifsUserFile): + return defaultUid + try: + fp = open(cifsUserFile) + content = fp.read() + fp.close() + except IOError, e: + Utils.log("failed to read file %s: %s" % (cifsUserFile, str(e))) + return False + + lines = content.strip().split() + if not lines: + return defaultUid + return int(lines[-1].split(":")[0]) + + +def setUid(uid, userName): + try: + fp = open(cifsUserFile, "a") + fp.write("%s:%s\n" % (uid, userName)) + fp.close() + return True + except IOError, e: + Utils.log("failed to write file %s: %s" % (cifsUserFile, str(e))) + return False + + +def main(): + if len(sys.argv) < 4: + sys.stderr.write("usage: %s SERVER_FILE USERNAME PASSWORD\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + serverFile = sys.argv[1] + userName = sys.argv[2] + password = sys.argv[3] + + uid = getLastUid() + if not uid: + sys.exit(10) + + uid += 1 + + rv = Utils.runCommand("grun.py %s add_user_cifs.py %s %s %s" % (serverFile, uid, userName, password)) + if rv == 0: + if not setUid(uid, userName): + sys.exit(11) + sys.exit(rv) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/delete_user_cifs_all.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/delete_user_cifs_all.py new file mode 100755 index 00000000..38dd8109 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/delete_user_cifs_all.py @@ -0,0 +1,53 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Utils + + +cifsUserFile = "/etc/glustermg/.users.cifs" + + +def removeUser(userName): + try: + fp = open(cifsUserFile) + content = fp.read() + fp.close() + except IOError, e: + Utils.log("failed to read file %s: %s" % (cifsUserFile, str(e))) + return False + + try: + fp = open(cifsUserFile, "w") + lines = content.strip().split() + for line in lines: + if line.split(":")[1] == userName: + continue + fp.write("%s\n" % line) + fp.close() + except IOError, e: + Utils.log("failed to write file %s: %s" % (cifsUserFile, str(e))) + return False + return True + + +def main(): + if len(sys.argv) < 3: + sys.stderr.write("usage: %s SERVER_LIST USERNAME\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + + serverList = sys.argv[1] + userName = sys.argv[2] + + rv = Utils.runCommand("grun.py %s delete_user_cifs.py %s" % (serverList, userName)) + if rv == 0: + if not removeUser(userName): + sys.exit(10) + sys.exit(rv) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/grun.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/grun.py new file mode 100755 index 00000000..ae93b7f2 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/grun.py @@ -0,0 +1,36 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. +# This file is part of Gluster Management Gateway. +# + +import os +import sys +import Utils + + +def main(): + sshCommandPrefix = "ssh -q -o BatchMode=yes -o GSSAPIAuthentication=no -o PasswordAuthentication=no -o StrictHostKeyChecking=no".split() + + if len(sys.argv) < 3: + sys.stderr.write("usage: %s SERVER_FILE COMMAND [ARGUMENTS]\n" % os.path.basename(sys.argv[0])) + sys.exit(-1) + serverFile = sys.argv[1] + command = sys.argv[2:] + + try: + fp = open(serverFile) + serverNameList = fp.readlines() + fp.close() + except IOError, e: + Utils.log("Failed to read server file %s: %s\n" % (serverFile, str(e))) + sys.exit(1) + + for serverName in serverNameList: + rv = Utils.runCommand(sshCommandPrefix + [serverName.strip()] + command) + print rv + + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway/WebContent/scripts/multicast-discover-servers.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/multicast-discover-servers.py new file mode 100755 index 00000000..ac434827 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/multicast-discover-servers.py @@ -0,0 +1,90 @@ +#!/usr/bin/python +# Copyright (C) 2009 Gluster, Inc. +# This file is part of Gluster Storage Platform. +# +# Gluster Storage Platform is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 of +# the License, or (at your option) any later version. +# +# Gluster Storage Platform 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see +# . + +import sys +import socket +import signal +import struct +import syslog +import Globals +import time +import Utils +from XmlHandler import * + +class TimeoutException(Exception): + pass + +def timeoutSignal(signum, frame): + raise TimeoutException, "Timed out" + +def serverDiscoveryRequest(multiCastGroup, port): + servers = [] + # Sending request to all the servers + socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) + + # Waiting for the response + socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + socketReceive.bind(('', port)) + mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) + + socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + sendtime = time.time() + socketSend.sendto("ServerDiscovery" % (sendtime), (multiCastGroup, port)) + + try: + while True: + response = socketReceive.recvfrom(200) + if not response: + continue + dom = XDOM() + dom.parseString(response[0]) + if not dom: + continue + if dom.getTextByTagRoute("request.name"): + continue + responsetime = dom.getTextByTagRoute("response.time") + servername = dom.getTextByTagRoute("response.servername") + if responsetime == str(sendtime): + servers.append(servername) + signal.signal(signal.SIGALRM, timeoutSignal) + signal.alarm(3) + except TimeoutException: + return servers + return None + +def main(): + syslog.openlog("discovery server request") + servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) + if not servers: + Utils.log(syslog.LOG_ERR, "Failed to discover new servers") + sys.exit(-1) + + servers = set(servers) + try: + for server in servers: + print server + except IOError: + Utils.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) + sys.exit(-1) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/src/com.gluster.storage.management.gateway/WebContent/ssl/gmg-ssl.keystore b/src/com.gluster.storage.management.gateway/WebContent/ssl/gmg-ssl.keystore new file mode 100644 index 00000000..2efe19b0 Binary files /dev/null and b/src/com.gluster.storage.management.gateway/WebContent/ssl/gmg-ssl.keystore differ diff --git a/src/com.gluster.storage.management.gateway/buckminster.cspex b/src/com.gluster.storage.management.gateway/buckminster.cspex new file mode 100644 index 00000000..31eb9d67 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/buckminster.cspex @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/build/glusterserver.ant b/src/com.gluster.storage.management.gateway/build/glusterserver.ant new file mode 100644 index 00000000..68a5bc08 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/build/glusterserver.ant @@ -0,0 +1,65 @@ + + + + + + + + + + + -------------------------------------------------- + compile - Compile + archive - Generate WAR file + -------------------------------------------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com.gluster.storage.management.gateway/src/META-INF/persistence.xml b/src/com.gluster.storage.management.gateway/src/META-INF/persistence.xml new file mode 100644 index 00000000..36b252ea --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/META-INF/persistence.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java new file mode 100644 index 00000000..1f577c89 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java @@ -0,0 +1,118 @@ +/** + * DefaultVolumeOptions.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.gateway.constants; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.model.VolumeOptionInfo; + +@Component +public class VolumeOptionsDefaults { + public List options; + + public VolumeOptionsDefaults() { + } + + /** + * @return list of volume option information objects + */ + public List getDefaults() { + return getVolumeOptionsInfo(); + } + + /** + * Fetches the list of all volume options with their information from GlusterFS and returns the same + * + * @return List of volume option information objects + */ + private List getVolumeOptionsInfo() { + List volumeOptionsInfo = new ArrayList(); + + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.stripe-block-size", + "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " + + CoreConstants.NEWLINE + + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern . ", + "*:128KB")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "cluster.self-heal-window-size", + "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", + "16")); + volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", + "cluster.data-self-heal-algorithm", "auto")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "network.frame-timeout", + "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", + "1800")); + volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", + "The time duration for which the client waits to check if the server is responsive.", "42")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", + "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); + volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", + "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.cache-refresh-timeout", + "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", + "1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", + "Size of the per-file write-behind buffer.", "1MB")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", + "performance.cache-max-file-size", "-1")); + volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", + "performance.cache-min-file-size", "0")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "performance.io-thread-count", + " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", + "16")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "diagnostics.latency-measurement", + "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", + "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", + "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", + "Changes the log-level of the bricks (servers).", "INFO")); + volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", + "Changes the log-level of the clients.", "INFO")); + volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", + "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", + "off")); + volumeOptionsInfo + .add(new VolumeOptionInfo( + "nfs.mem-factor", + "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", + "15")); + volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); + + return volumeOptionsInfo; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ClusterInfo.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ClusterInfo.java new file mode 100644 index 00000000..3e5ea01a --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ClusterInfo.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * 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.gateway.data; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +import org.hibernate.cfg.AnnotationConfiguration; +import org.hibernate.tool.hbm2ddl.SchemaExport; + +@Entity(name="cluster_info") +public class ClusterInfo { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @OneToMany(mappedBy="cluster") + private List servers = new ArrayList(); + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setServers(List servers) { + this.servers = servers; + } + + public List getServers() { + return servers; + } + + public void addServer(ServerInfo server) { + servers.add(server); + } + + public static void main(String args[]) { + AnnotationConfiguration config = new AnnotationConfiguration(); + config.addAnnotatedClass(ClusterInfo.class); + config.addAnnotatedClass(ServerInfo.class); + config.configure(); + new SchemaExport(config).create(true, true); + } + +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java new file mode 100644 index 00000000..0802fe93 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java @@ -0,0 +1,48 @@ +/** + * GlusterDataSource.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.gateway.data; + +import javax.servlet.ServletContext; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.stereotype.Component; + +@Component +public class GlusterDataSource extends DriverManagerDataSource { + @Autowired + ServletContext servletContext; + + public GlusterDataSource() { + setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); + + setUsername("gluster"); + // TODO: change to a stronger (encrypted) password + setPassword("gluster"); + } + + public DriverManagerDataSource getDataSource() { + // Database directory = work/data relative to context root + setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); + + return this; + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/PersistenceDao.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/PersistenceDao.java new file mode 100644 index 00000000..eb7d6514 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/PersistenceDao.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.gateway.data; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.PersistenceUnit; +import javax.persistence.Query; + +/** + * + */ +public class PersistenceDao { + private Class type; + + private EntityManager entityManager; + + @PersistenceUnit + private EntityManagerFactory entityManagerFactory; + + public PersistenceDao(Class type) { + this.type = type; + } + + public EntityTransaction startTransaction() { + EntityTransaction txn = getEntityManager().getTransaction(); + txn.begin(); + return txn; + } + + private synchronized EntityManager getEntityManager() { + if (entityManager == null) { + entityManager = entityManagerFactory.createEntityManager(); + } + return entityManager; + } + + public Object getSingleResult(String query) { + return getEntityManager().createQuery(query).getSingleResult(); + } + + public Object getSingleResult(String queryString, String... params) { + return createQuery(queryString, params).getSingleResult(); + } + + private Query createQuery(String queryString, String... params) { + Query query = getEntityManager().createQuery(queryString); + for (int i = 0; i < params.length; i++) { + query.setParameter(i + 1, params[i]); + } + return query; + } + + public Object getSingleResultFromSQL(String sqlQuery) { + return getEntityManager().createNativeQuery(sqlQuery).getSingleResult(); + } + + @SuppressWarnings("rawtypes") + public List findBySQL(String sqlQuery) { + return getEntityManager().createNativeQuery(sqlQuery).getResultList(); + } + + public T findById(int id) { + return getEntityManager().find(type, id); + } + + @SuppressWarnings("unchecked") + public List findAll() { + return getEntityManager().createQuery("select t from " + type.getName() + " t").getResultList(); + } + + @SuppressWarnings("unchecked") + public List findBy(String whereClause) { + return getEntityManager().createQuery("select t from " + type.getName() + " t where " + whereClause) + .getResultList(); + } + + @SuppressWarnings("unchecked") + public List findBy(String whereClause, String... params) { + return createQuery("select t from " + type.getName() + " t where " + whereClause, params).getResultList(); + } + + public void save(Object obj) { + getEntityManager().persist(obj); + } + + public T update(T obj) { + return getEntityManager().merge(obj); + } + + public void delete(Object obj) { + getEntityManager().remove(obj); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ServerInfo.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ServerInfo.java new file mode 100644 index 00000000..a3f8c920 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/data/ServerInfo.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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.gateway.data; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +/** + * + */ +@Entity(name="server_info") +public class ServerInfo { + @Id + @GeneratedValue + private Integer id; + + private String name; + + @ManyToOne + @JoinColumn(name="cluster_id") + private ClusterInfo cluster; + + public ServerInfo() { + } + + public ServerInfo(String name) { + setName(name); + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setCluster(ClusterInfo cluster) { + this.cluster = cluster; + } + + public ClusterInfo getCluster() { + return cluster; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuditFilter.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuditFilter.java new file mode 100644 index 00000000..31810123 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuditFilter.java @@ -0,0 +1,38 @@ +/** + * + */ +package com.gluster.storage.management.gateway.filters; + +import com.sun.jersey.spi.container.ContainerRequest; +import com.sun.jersey.spi.container.ContainerRequestFilter; +import com.sun.jersey.spi.container.ContainerResponse; +import com.sun.jersey.spi.container.ContainerResponseFilter; +import com.sun.jersey.spi.container.ResourceFilter; + +/** + * Resource filter for maintaining audit trail of resource access + */ +public class AuditFilter implements ResourceFilter, ContainerRequestFilter, ContainerResponseFilter { + + @Override + public ContainerRequestFilter getRequestFilter() { + return this; + } + + @Override + public ContainerResponseFilter getResponseFilter() { + return this; + } + + @Override + public ContainerRequest filter(ContainerRequest req) { + System.out.println("REQUEST: [" + req.getMethod() + "][" + req.getPath() + "]"); + return req; + } + + @Override + public ContainerResponse filter(ContainerRequest req, ContainerResponse response) { + System.out.println("RESPONSE: [" + req.getMethod() + "][" + req.getPath() + "]"); + return response; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java new file mode 100644 index 00000000..73a1085e --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * 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.gateway.filters; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import javax.ws.rs.core.Response; + +/** + * @author root + * + */ +public class AuthenticationFailureFilter implements Filter { + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#destroy() + */ + @Override + public void destroy() { + // TODO Auto-generated method stub + + } + + public class CharResponseWrapper extends HttpServletResponseWrapper { + private CharArrayWriter output; + + public String toString() { + return output.toString(); + } + + public CharResponseWrapper(HttpServletResponse response) { + super(response); + output = new CharArrayWriter(); + } + + public PrintWriter getWriter() { + return new PrintWriter(output); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) + */ + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, + ServletException { + HttpServletRequest request = (HttpServletRequest) req; + if (request.getRequestURI().contains("download")) { + chain.doFilter(req, res); + return; + } + + CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) res); + chain.doFilter(req, wrapper); + + if(wrapper.getStatus() == Response.Status.UNAUTHORIZED.ordinal()) { + PrintWriter out = res.getWriter(); + out.println("1Authentication Failed!"); + } + } + + /* + * (non-Javadoc) + * + * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + */ + @Override + public void init(FilterConfig arg0) throws ServletException { + // TODO Auto-generated method stub + + } + +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java new file mode 100644 index 00000000..1c480f3f --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java @@ -0,0 +1,31 @@ +/** + * + */ +package com.gluster.storage.management.gateway.filters; + +import java.util.ArrayList; +import java.util.List; + +import com.sun.jersey.api.model.AbstractMethod; +import com.sun.jersey.spi.container.ResourceFilter; +import com.sun.jersey.spi.container.ResourceFilterFactory; + +/** + * Gluster resource filter factory. As of now, this creates only one filter - the audit filter {@code AuditFilter} + */ +public class GlusterResourceFilterFactory implements ResourceFilterFactory { + + public GlusterResourceFilterFactory() { + } + + /* (non-Javadoc) + * @see com.sun.jersey.spi.container.ResourceFilterFactory#create(com.sun.jersey.api.model.AbstractMethod) + */ + @Override + public List create(AbstractMethod arg0) { + List filters = new ArrayList(); + filters.add(new AuditFilter()); + + return filters; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java new file mode 100644 index 00000000..9fc4fceb --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; + +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.StreamingOutput; +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 + * 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(); + } + + protected StreamingOutput createStreamingOutput(final byte[] data) { + return new StreamingOutput() { + @Override + public void write(OutputStream output) throws IOException { + output.write(data); + } + }; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java new file mode 100644 index 00000000..d0da6696 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * 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.gateway.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.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.response.ClusterNameListResponse; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.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; + private static final Logger logger = Logger.getLogger(ClustersResource.class); + + @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()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); + } + + clusterService.createCluster(clusterName); + return createdResponse(clusterName); + } + + @PUT + public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, + @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { + if(clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + if(knownServer == null || knownServer.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); + } + + if(clusterService.getCluster(clusterName) != null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); + } + + ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); + if(mappedCluster != null) { + throw new GlusterValidationException("Server [" + knownServer + "] is already present in cluster [" + + mappedCluster.getName() + "]!"); + } + + clusterService.registerCluster(clusterName, knownServer); + return noContentResponse(clusterName); + } + + @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") + @DELETE + public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { + if(clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if(cluster == null) { + throw new GlusterValidationException("Cluster [" + clusterName + "] does not exist!"); + } + + clusterService.unregisterCluster(cluster); + return noContentResponse(); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java new file mode 100644 index 00000000..2d07bd24 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * 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.gateway.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.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.sun.jersey.api.core.InjectParam; +import com.sun.jersey.spi.resource.Singleton; + +@Component +@Singleton +@Path(RESOURCE_PATH_DISCOVERED_SERVERS) +public class DiscoveredServersResource extends AbstractResource { + @InjectParam + protected ServerUtil serverUtil; + + @InjectParam + protected GlusterUtil glusterUtil; + + 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.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java new file mode 100644 index 00000000..3a316c0c --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import com.gluster.storage.management.core.exceptions.GlusterValidationException; + +@Provider +public class GenericExceptionMapper implements ExceptionMapper { + + /* (non-Javadoc) + * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) + */ + @Override + public Response toResponse(Exception exception) { + ResponseBuilder builder; + if (exception instanceof GlusterValidationException) { + builder = Response.status(Response.Status.BAD_REQUEST); + } else { + builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); + } + + String errMsg = exception.getMessage(); + if(errMsg == null) { + errMsg = "Following exception occurred : " + exception.getClass().getName(); + StackTraceElement[] stackTrace = exception.getStackTrace(); + if(stackTrace.length > 0) { + errMsg += " at [" + stackTrace[0].getClassName() + "][" + stackTrace[0].getLineNumber() + "]"; + } + } + return builder.entity(errMsg).type(MediaType.TEXT_PLAIN).build(); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java new file mode 100644 index 00000000..e6e4f9d6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java @@ -0,0 +1,487 @@ +/******************************************************************************* + * 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.gateway.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE; +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.QUERY_PARAM_DETAILS; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_INTERFACE; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_PERIOD; +import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; +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_STATISTICS; +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY; +import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK; + +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.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.constants.RESTConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.response.GlusterServerListResponse; +import com.gluster.storage.management.core.response.ServerNameListResponse; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.services.GlusterServerService; +import com.gluster.storage.management.gateway.tasks.InitializeDiskTask; +import com.gluster.storage.management.gateway.utils.CpuStatsFactory; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.MemoryStatsFactory; +import com.gluster.storage.management.gateway.utils.NetworkStatsFactory; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.gluster.storage.management.gateway.utils.StatsFactory; +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 AbstractResource { + + public static final String HOSTNAMETAG = "hostname:"; + + @InjectParam + private DiscoveredServersResource discoveredServersResource; + + @InjectParam + private TasksResource taskResource; + + @InjectParam + private ClusterService clusterService; + + @InjectParam + private SshUtil sshUtil; + + @InjectParam + private CpuStatsFactory cpuStatsFactory; + + @InjectParam + private MemoryStatsFactory memoryStatsFactory; + + @InjectParam + private NetworkStatsFactory networkStatsFactory; + + @InjectParam + private ServerUtil serverUtil; + + @InjectParam + private GlusterUtil glusterUtil; + + @InjectParam + private GlusterServerService glusterServerService; + + @GET + @Produces(MediaType.APPLICATION_JSON) + public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { + return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); + } + + private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { + if(fetchDetails == null) { + // by default, fetch the server details + fetchDetails = true; + } + + 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); + } + + try { + glusterServers = glusterServerService.getGlusterServers(clusterName, fetchDetails); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + + if(fetchDetails) { + return okResponse(new GlusterServerListResponse(glusterServers), mediaType); + } else { + // no details to be fetched. Return list of server names. + return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType); + } + } + + private List getServerNames(List glusterServers) { + List serverNames = new ArrayList(); + for(GlusterServer server : glusterServers) { + serverNames.add(server.getName()); + } + return serverNames; + } + + @GET + @Path("{" + PATH_PARAM_SERVER_NAME + "}") + @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("{" + PATH_PARAM_SERVER_NAME + "}") + @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(glusterServerService.getGlusterServer(clusterName, serverName, true), mediaType); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + 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."); + } + + String hostName = serverUtil.fetchHostName(serverName); + 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, hostName); + } 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()); + } + } + clusterService.unmapServerFromCluster(clusterName, serverName); + + 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); + } + + // 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, + @FormParam(FORM_PARAM_FSTYPE) String fsType) { + + 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!"); + } + + if (fsType == null || fsType.isEmpty()) { + return badRequestResponse("Parameter [" + FORM_PARAM_FSTYPE + "] is missing in request!"); + } + + InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName, fsType); + try { + initializeTask.start(); + // Check the initialize disk status + TaskStatus taskStatus = initializeTask.checkStatus(); + initializeTask.getTaskInfo().setStatus(taskStatus); + taskResource.addTask(initializeTask); + + return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" + + initializeTask.getId()); + } catch (Exception e) { + return errorResponse(e.getMessage()); + } + } + + @GET + @Produces(MediaType.APPLICATION_XML) + @Path(RESOURCE_STATISTICS) + public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_XML); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path(RESOURCE_STATISTICS) + public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { + return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_JSON); + } + + @GET + @Produces(MediaType.APPLICATION_XML) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_XML); + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) + public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, + @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, + @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { + return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_JSON); + } + + private Response getAggregaredPerformanceData(String clusterName, String type, String period, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + + ClusterInfo cluster = clusterService.getCluster(clusterName); + if (cluster == null) { + return notFoundResponse("Cluster [" + clusterName + "] not found!"); + } + + if (cluster.getServers().isEmpty()) { + // cluster is empty. return empty stats. + return okResponse(new ServerStats(), mediaType); + } + + List serverNames = getServerNames(glusterServerService.getGlusterServers(clusterName, false)); + return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); + } + + private Response getPerformanceData(String clusterName, String serverName, String type, String period, String networkInterface, String mediaType) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterValidationException("Server name must not be empty!"); + } + + if (type == null || type.isEmpty()) { + throw new GlusterValidationException("Statistics type name must not be empty!"); + } + + if (period == null || period.isEmpty()) { + throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); + } + + return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); + } + + private StatsFactory getStatsFactory(String type) { + if(type.equals(STATISTICS_TYPE_CPU)) { + return cpuStatsFactory; + } else if(type.equals(STATISTICS_TYPE_MEMORY)) { + return memoryStatsFactory; + } else if(type.equals(STATISTICS_TYPE_NETWORK)) { + return networkStatsFactory; + } else { + throw new GlusterValidationException("Invalid server statistics type [" + type + "]. Valid values are [" + + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); + } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java new file mode 100644 index 00000000..34dad497 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java @@ -0,0 +1,153 @@ +/** + * KeysResource.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.gateway.resources.v1_0; + +import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_KEYS; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +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.utils.FileUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.multipart.FormDataParam; + +@Path(RESOURCE_PATH_KEYS) +public class KeysResource extends AbstractResource { + private static final Logger logger = Logger.getLogger(KeysResource.class); + private ProcessUtil processUtil = new ProcessUtil(); + + @GET + @Produces(MediaType.APPLICATION_OCTET_STREAM) + public Response exportSshkeys() { + File archiveFile = new File(createSskKeyZipFile()); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); + } + + private String createSskKeyZipFile() { + String targetDir = System.getProperty("java.io.tmpdir"); + String zipFile = targetDir + "ssh-keys.tar"; + String sourcePemFile = SshUtil.PRIVATE_KEY_FILE.getAbsolutePath(); + String sourcePubKeyFile = SshUtil.PUBLIC_KEY_FILE.getAbsolutePath(); + String targetPemFile = targetDir + File.separator + SshUtil.PRIVATE_KEY_FILE.getName(); + String targetPubKeyFile = targetDir + File.separator + SshUtil.PUBLIC_KEY_FILE.getName(); + + if (!SshUtil.PRIVATE_KEY_FILE.isFile()) { + throw new GlusterRuntimeException("No private key file [" + SshUtil.PRIVATE_KEY_FILE.getName() + "] found!" ); + } + + if (!SshUtil.PUBLIC_KEY_FILE.isFile()) { + throw new GlusterRuntimeException("No public key file [" + SshUtil.PUBLIC_KEY_FILE.getName() + "] found!" ); + } + + // Copy keys to temp folder + ProcessResult result = processUtil.executeCommand("cp", sourcePemFile, targetPemFile); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); + } + result = processUtil.executeCommand("cp", sourcePubKeyFile, targetPubKeyFile); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); + } + + // To compress the key files + result = processUtil.executeCommand("tar", "cvf", zipFile, "-C", "/tmp", SshUtil.PRIVATE_KEY_FILE.getName(), + SshUtil.PUBLIC_KEY_FILE.getName()); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Failed to compress key files! [" + result.getOutput() + "]"); + } + + // To remove the copied key files + try { + processUtil.executeCommand("rm", "-f", targetPemFile, targetPubKeyFile); // Ignore the errors if any + } catch (Exception e) { + logger.warn(e.toString()); + } + return zipFile; + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response importSshKeys(@FormDataParam("file") InputStream uploadedInputStream) { + File uploadedFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "keys.tar"); + String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + + writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); + + // To backup existing SSH pem and public keys, if exist. + if (SshUtil.PRIVATE_KEY_FILE.isFile()) { + if (!SshUtil.PRIVATE_KEY_FILE.renameTo(new File(SshUtil.PRIVATE_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup pem key!"); + } + } + + if (SshUtil.PUBLIC_KEY_FILE.isFile()) { + if (!SshUtil.PUBLIC_KEY_FILE + .renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { + throw new GlusterRuntimeException("Unable to backup public key!"); + } + } + // Extract SSH pem and public key files. + ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", + SshUtil.SSH_AUTHORIZED_KEYS_DIR_LOCAL); + uploadedFile.delete(); + if (!output.isSuccess()) { + throw new GlusterRuntimeException(output.getOutput()); + } + return createdResponse("SSH Key imported successfully"); + } + + // save uploaded file to the file (with path) + private void writeToFile(InputStream inputStream, String toFile) { + try { + int read = 0; + byte[] bytes = new byte[1024]; + + OutputStream out = new FileOutputStream(new File(toFile)); + while ((read = inputStream.read(bytes)) != -1) { + out.write(bytes, 0, read); + } + out.flush(); + out.close(); + } catch (IOException e) { + throw new GlusterRuntimeException(e.getMessage()); + } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java new file mode 100644 index 00000000..e5874f4b --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java @@ -0,0 +1,194 @@ +/** + * 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.gateway.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 org.springframework.stereotype.Component; + +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.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.response.TaskInfoListResponse; +import com.gluster.storage.management.gateway.tasks.Task; +import com.sun.jersey.spi.resource.Singleton; + +@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) +@Singleton +@Component +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; + } + + public List getAllTasks() { + List tasks = new ArrayList(); + for (Map.Entry entry : tasksMap.entrySet()) { + checkTaskStatus(entry.getKey()); + tasks.add( (Task) entry.getValue()); + } + return tasks; + } + + @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); + // No status check required if the task already complete or failure + if (task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_FAILURE + || task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + return task; + } + 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(); + clearTask(taskId, taskOperation); // Stop and remove from the task list + } 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 clearTask(@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.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java new file mode 100644 index 00000000..4b2701f2 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/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.gateway.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.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java new file mode 100644 index 00000000..45df1ae7 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java @@ -0,0 +1,989 @@ +/** + * 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.gateway.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.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.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.log4j.Logger; + +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.exceptions.GlusterValidationException; +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.gateway.constants.VolumeOptionsDefaults; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.tasks.MigrateBrickTask; +import com.gluster.storage.management.gateway.tasks.RebalanceVolumeTask; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.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"; + private static final Logger logger = Logger.getLogger(VolumesResource.class); + + @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 void performOperation(String volumeName, String operation, GlusterServer onlineServer) { + if (operation.equals(TASK_START)) { + glusterUtil.startVolume(volumeName, onlineServer.getName()); + } else if (operation.equals(TASK_STOP)) { + glusterUtil.stopVolume(volumeName, onlineServer.getName()); + } else { + throw new GlusterValidationException("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) { + Status status; + try { + status = 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 + "]"); + } + status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); + } + if (!status.isSuccess()) { + throw new GlusterRuntimeException(status.toString()); + } + } + + @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.executeScriptOnServer(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.executeScriptOnServer(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.executeScriptOnServer(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); + File archiveFile = new File(downloadLogs(volume)); + byte[] data = FileUtil.readFileAsByteArray(archiveFile); + archiveFile.delete(); + return streamingOutputResponse(createStreamingOutput(data)); + } catch (Exception e) { + logger.error("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]! [" + + e.getStackTrace() + "]"); + throw (GlusterRuntimeException) e; + } + } + + + 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 getLayout(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 layout; + } + + private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, + Boolean isForcedDataMigrate) { + RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName, getLayout( + isFixLayout, isMigrateData, isForcedDataMigrate)); + 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(); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java new file mode 100644 index 00000000..e806051c --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java @@ -0,0 +1,31 @@ +/** + * GlusterUserDetailsService.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.gateway.security; + +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * + */ +public interface GlusterUserDetailsService extends UserDetailsService { + void changePassword(String username, String password); +} + diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/UserAuthDao.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/UserAuthDao.java new file mode 100644 index 00000000..bdc3b19e --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/security/UserAuthDao.java @@ -0,0 +1,42 @@ +/** + * UserAuthDao.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.gateway.security; + +import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; + +/** + * @author root + * + */ +public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { + + /* + * (non-Javadoc) + * + * @see com.gluster.storage.management.gateway.security.GlusterUserDetailsService#changePassword(java.lang.String, + * java.lang.String) + */ + @Override + public void changePassword(String username, String password) { + getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); + } + +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/ClusterService.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/ClusterService.java new file mode 100644 index 00000000..e01c5096 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/ClusterService.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * 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.gateway.services; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityTransaction; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.utils.LRUCache; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; + +/** + * Service class for functionality related to clusters + */ +@Component +public class ClusterService { + @Autowired + private PersistenceDao clusterDao; + + @Autowired + private PersistenceDao serverDao; + + @Autowired + private GlusterUtil glusterUtil; + + @Autowired + private SshUtil sshUtil; + + @Autowired + private ServerUtil serverUtil; + + private LRUCache onlineServerCache = new LRUCache(3); + + private static final Logger logger = Logger.getLogger(ClusterService.class); + + public void addOnlineServer(String clusterName, GlusterServer server) { + onlineServerCache.put(clusterName, server); + } + + public void removeOnlineServer(String clusterName) { + onlineServerCache.remove(clusterName); + } + + // uses cache + public GlusterServer getOnlineServer(String clusterName, String exceptServerName) { + GlusterServer server = onlineServerCache.get(clusterName); + if (server != null && !server.getName().equals(exceptServerName)) { + return server; + } + + return getNewOnlineServer(clusterName, exceptServerName); + } + + public GlusterServer getNewOnlineServer(String clusterName) { + return getNewOnlineServer(clusterName, ""); + } + + public GlusterServer getOnlineServer(String clusterName) { + return getOnlineServer(clusterName, ""); + } + + // Doesn't use cache + public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) { + ClusterInfo cluster = getCluster(clusterName); + if (cluster == null) { + throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!"); + } + + for (ServerInfo serverInfo : cluster.getServers()) { + GlusterServer server = new GlusterServer(serverInfo.getName()); + try { + serverUtil.fetchServerDetails(server); // Online status come with server details + // server is online. add it to cache and return + if (server.isOnline() && !server.getName().equals(exceptServerName)) { + addOnlineServer(clusterName, server); + return server; + } + } catch (ConnectionException e) { + // server is offline. continue checking next one. + continue; + } + } + + // no online server found. + throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); + } + + public List getAllClusters() { + return clusterDao.findAll(); + } + + public ClusterInfo getCluster(String clusterName) { + List clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase()); + if(clusters.size() == 0) { + return null; + } + + return clusters.get(0); + } + + public ClusterInfo getClusterForServer(String serverName) { + List servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase()); + if(servers.size() == 0) { + return null; + } + + return servers.get(0).getCluster(); + } + + public void createCluster(String clusterName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + try { + clusterDao.save(cluster); + txn.commit(); + } catch (RuntimeException e) { + txn.rollback(); + logger.error("Exception while trying to save cluster [" + clusterName + "] : [" + e.getMessage() + "]", e); + throw e; + } + } + + public void registerCluster(String clusterName, String knownServer) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = new ClusterInfo(); + cluster.setName(clusterName); + + GlusterServer server = new GlusterServer(knownServer); + try { + List glusterServers = glusterUtil.getGlusterServers(server); + List servers = new ArrayList(); + 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) { + logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); + txn.rollback(); + logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); + 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(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 { + for(ServerInfo server : cluster.getServers()) { + clusterDao.delete(server); + } + cluster.getServers().clear(); + clusterDao.update(cluster); + clusterDao.delete(cluster); + txn.commit(); + } catch (RuntimeException e) { + logger.error("Error in unregistering cluster [" + cluster.getName() + "] : " + e.getMessage(), e); + txn.rollback(); + throw e; + } + } + + public void mapServerToCluster(String clusterName, String serverName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = getCluster(clusterName); + ServerInfo server = new ServerInfo(serverName); + server.setCluster(cluster); + try { + clusterDao.save(server); + cluster.addServer(server); + clusterDao.update(cluster); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + throw new GlusterRuntimeException("Couldn't create cluster-server mapping [" + clusterName + "][" + + serverName + "]! Error: " + e.getMessage(), e); + } + } + + public void unmapServerFromCluster(String clusterName, String serverName) { + EntityTransaction txn = clusterDao.startTransaction(); + ClusterInfo cluster = getCluster(clusterName); + List servers = cluster.getServers(); + for(ServerInfo server : servers) { + if(server.getName().equals(serverName)) { + servers.remove(server); + clusterDao.delete(server); + break; + } + } + try { + clusterDao.update(cluster); + txn.commit(); + } catch(Exception e) { + txn.rollback(); + throw new GlusterRuntimeException("Couldn't unmap server [" + serverName + "] from cluster [" + clusterName + + "]! Error: " + e.getMessage(), e); + } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/GlusterServerService.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/GlusterServerService.java new file mode 100644 index 00000000..d1437cec --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/services/GlusterServerService.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * 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.gateway.services; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.exceptions.GlusterValidationException; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; + +/** + * + */ +@Component +public class GlusterServerService { + @Autowired + protected ServerUtil serverUtil; + + @Autowired + private ClusterService clusterService; + + @Autowired + private GlusterUtil glusterUtil; + + public void fetchServerDetails(GlusterServer server) { + try { + server.setStatus(SERVER_STATUS.ONLINE); + serverUtil.fetchServerDetails(server); + } catch (ConnectionException e) { + server.setStatus(SERVER_STATUS.OFFLINE); + } + } + + public List getGlusterServers(String clusterName, boolean fetchDetails) { + List glusterServers; + GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); + if (onlineServer == null) { + throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); + } + + try { + glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); + } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); + } + return glusterServers; + } + + private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { + 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); + } + + if (fetchDetails) { + String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); + if (!errMsg.isEmpty()) { + throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); + } + } + return glusterServers; + } + + private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { + String errMsg = ""; + + for (GlusterServer server : glusterServers) { + try { + fetchServerDetails(server); + } catch (Exception e) { + errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; + } + } + return errMsg; + } + + public GlusterServer getGlusterServer(String clusterName, String serverName, Boolean fetchDetails) { + if (clusterName == null || clusterName.isEmpty()) { + throw new GlusterValidationException("Cluster name must not be empty!"); + } + + if (serverName == null || serverName.isEmpty()) { + throw new GlusterValidationException("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 + "]"); + } + + return getGlusterServer(clusterName, serverName, onlineServer, fetchDetails); + } + + private GlusterServer getGlusterServer(String clusterName, String serverName, GlusterServer onlineServer, + Boolean fetchDetails) { + 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 (fetchDetails && server.isOnline()) { + fetchServerDetails(server); + } + return server; + } + + public boolean isValidServer(String clusterName, String serverName) { + try { + GlusterServer server = getGlusterServer(clusterName, serverName, false); + return server != null; + } catch(Exception e) { + return false; + } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java new file mode 100644 index 00000000..6d525785 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java @@ -0,0 +1,162 @@ +/** + * GlusterServerInitializer.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.gateway.tasks; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.apache.derby.tools.ij; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.support.JdbcDaoSupport; +import org.springframework.security.authentication.encoding.PasswordEncoder; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; + +/** + * Initializes the Gluster Management Server. + */ +public class InitServerTask extends JdbcDaoSupport { + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private String appVersion; + + @Autowired + private PersistenceDao clusterDao; + + @Autowired + ServletContext servletContext; + + private static final String SCRIPT_DIR = "data/scripts/"; + + public void securePasswords() { + getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { + @Override + public void processRow(ResultSet rs) throws SQLException { + String username = rs.getString(1); + String password = rs.getString(2); + String encodedPassword = passwordEncoder.encodePassword(password, null); + getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); + logger.debug("Updating password for username: " + username); + } + }); + } + + private void executeScript(File script) { + ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); + int numOfExceptions; + try { + numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), new FileInputStream( + script), CoreConstants.ENCODING_UTF8, sqlOut, CoreConstants.ENCODING_UTF8); + String output = sqlOut.toString(); + sqlOut.close(); + logger.debug("Data script [" + script.getName() + "] returned with exit status [" + numOfExceptions + + "] and output [" + output + "]"); + if (numOfExceptions != 0) { + throw new GlusterRuntimeException("Server data initialization script [ " + script.getName() + + "] failed with [" + numOfExceptions + "] exceptions! [" + output + "]"); + } + } catch (Exception ex) { + throw new GlusterRuntimeException("Server data initialization script [" + script.getName() + "] failed!", + ex); + } + } + + private void initDatabase() { + logger.info("Initializing server data..."); + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + appVersion)); + + securePasswords(); // encrypt the passwords + } + + private File getDirFromRelativePath(String relativePath) { + String scriptDirPath = servletContext.getRealPath(relativePath); + File scriptDir = new File(scriptDirPath); + return scriptDir; + } + + private void executeScriptsFrom(File scriptDir) { + if (!scriptDir.exists()) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] doesn't exist!"); + } + + List scripts = Arrays.asList(scriptDir.listFiles()); + if(scripts.size() == 0) { + throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] is empty!"); + } + + Collections.sort(scripts); + for (File script : scripts) { + executeScript(script); + } + } + + /** + * Initializes the server database, if running for the first time. + */ + public synchronized void initServer() { + try { + String dbVersion = getDBVersion(); + if (!appVersion.equals(dbVersion)) { + logger.info("App version [" + appVersion + "] differs from data version [" + dbVersion + + "]. Trying to upgrade data..."); + upgradeData(dbVersion, appVersion); + } + } catch (Exception ex) { + logger.info("No cluster created yet. DB version query failed with error [" + ex.getMessage() + "]", ex); + // Database not created yet. Create it! + initDatabase(); + } + + // For development time debugging. To be removed later. + List clusters = clusterDao.findAll(); + logger.info(clusters.size()); + + if (clusters.size() > 0) { + for (ClusterInfo cluster : clusters) { + logger.info("Cluster: [" + cluster.getId() + "][" + cluster.getName() + "]"); + } + } else { + + } + } + + private void upgradeData(String fromVersion, String toVersion) { + executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + fromVersion + "-" + toVersion)); + } + + private String getDBVersion() { + return (String) clusterDao.getSingleResultFromSQL("select version from version"); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java new file mode 100644 index 00000000..e7da1de6 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java @@ -0,0 +1,164 @@ +/** + * InitializeDiskTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.constants.GlusterConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.core.util.Base64; + +public class InitializeDiskTask extends Task { + + private static final String INITIALIZE_DISK_SCRIPT = "format_device.py"; + + private String serverName; + private String diskName; + private String fsType; + private ServerUtil serverUtil; + private GlusterUtil glusterUtil; + + public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, String fsType) { + super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" + + diskName, false, false, false); + + setServerName(serverName); + setDiskName(diskName); + setFsType(fsType); + taskInfo.setName(getId()); + init(); + } + + public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { + super(clusterService, clusterName, info); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + glusterUtil = ctx.getBean(GlusterUtil.class); + serverUtil = ctx.getBean(ServerUtil.class); + } + + @Override + public String getId() { + return new String( + Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void stop() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Stop/Pause/Resume is not supported in Disk Initialization"))); + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } + + @Override + public TASK_TYPE getType() { + return TASK_TYPE.DISK_FORMAT; + } + + + @Override + public void start() { + try { + startInitializeDisk(serverName); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } + } + + private void startInitializeDisk(String serverName) { + String fsTypeCommand = (getFsType().equals(GlusterConstants.FSTYPE_DEFAULT)) ? "" : " -t " + getFsType(); + + String output = (String) serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_SCRIPT + + fsTypeCommand + " " + getDiskName(), String.class); + TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output)); + taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); + getTaskInfo().setStatus(taskStatus); + } + + @Override + public TaskStatus checkStatus() { + + try { + return glusterUtil.getInitializingDeviceStatus(serverName, getDiskName()); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); + } + } + + public void setDiskName(String diskName) { + this.diskName = diskName; + } + + public String getDiskName() { + return diskName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + public String getServerName() { + return serverName; + } + + public void setFsType(String fsType) { + this.fsType = fsType; + } + + public String getFsType() { + return fsType; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java new file mode 100644 index 00000000..694067aa --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java @@ -0,0 +1,227 @@ +/** + * MigrateDiskTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.sun.jersey.core.util.Base64; + +public class MigrateBrickTask extends Task { + + private String fromBrick; + private String toBrick; + private Boolean autoCommit; + private GlusterUtil glusterUtil; + + public String getFromBrick() { + return fromBrick; + } + + public void setFromBrick(String fromBrick) { + this.fromBrick = fromBrick; + } + + public String getToBrick() { + return toBrick; + } + + public void setToBrick(String toBrick) { + this.toBrick = toBrick; + } + + public Boolean getAutoCommit() { + return autoCommit; + } + + public void setAutoCommit(Boolean autoCommit) { + this.autoCommit = autoCommit; + } + + public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, + String toBrick) { + super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" + + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); + setFromBrick(fromBrick); + setToBrick(toBrick); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + glusterUtil = ctx.getBean(GlusterUtil.class); + } + + @Override + public String getId() { + return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" + + toBrick)); + } + + @Override + public void start() { + try { + startMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone Offline. try with a new one. + startMigration(getNewOnlineServer().getName()); + } + } + + private void startMigration(String onlineServerName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServerName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "start"); + if (processResult.getOutput().trim().matches(".*started successfully$")) { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); + return; + } + } + + @Override + public void pause() { + try { + pauseMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + pauseMigration(getNewOnlineServer().getName()); + } + } + + private void pauseMigration(String onlineServer) { + ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServer, taskInfo.getReference(), + getFromBrick(), getToBrick(), "pause"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*paused successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_PAUSE); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + return; + } + } + + @Override + public void resume() { + start(); + } + + @Override + public void commit() { + try { + commitMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + commitMigration(getNewOnlineServer().getName()); + } + } + + private void commitMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "commit"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches(".*commit successful$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + } + } + } + + @Override + public void stop() { + try { + stopMigration(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + stopMigration(getNewOnlineServer().getName()); + } + } + + private void stopMigration(String serverName) { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, taskInfo.getReference(), getFromBrick(), + getToBrick(), "abort"); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.getOutput().trim().matches(".*aborted successfully$")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + getTaskInfo().setStatus(taskStatus); + } + } + + @Override + public TaskStatus checkStatus() { + try { + return checkMigrationStatus(getOnlineServer().getName()); + } catch (ConnectionException e) { + // online server might have gone offline. try with a new one. + return checkMigrationStatus(getNewOnlineServer().getName()); + } + } + + private TaskStatus checkMigrationStatus(String serverName) { + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE) { + return getTaskInfo().getStatus(); + } + // For committed task, status command (CLI) is invalid, just return current status + if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { + return getTaskInfo().getStatus(); + } + + + TaskStatus taskStatus = new TaskStatus(); + try { + ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), + getFromBrick(), getToBrick(), "status"); + if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$") + || processResult.getOutput().trim().matches("^Number of files migrated = 0 .*Current file=")) { + // Note: Workaround - if no file in the volume brick to migrate, Gluster CLI is not giving proper + // (complete) status + taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); + if (autoCommit) { + commitMigration(serverName); + return getTaskInfo().getStatus(); // return the committed status + } else { + taskStatus.setMessage(processResult.getOutput().trim() + .replaceAll("Migration complete", "Commit pending")); + } + } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); + } catch (Exception e) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(e.getMessage()); + } + taskInfo.setStatus(taskStatus); // Update the task status + return taskStatus; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java new file mode 100644 index 00000000..c53f0252 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java @@ -0,0 +1,129 @@ +/** + * RebalanceVolumeTask.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.gateway.tasks; + +import org.springframework.context.ApplicationContext; +import org.springframework.web.context.ContextLoader; + +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.utils.GlusterUtil; +import com.gluster.storage.management.gateway.utils.ServerUtil; +import com.gluster.storage.management.gateway.utils.SshUtil; +import com.sun.jersey.core.util.Base64; + +public class RebalanceVolumeTask extends Task { + + private String layout; + private String serverName; + private ServerUtil serverUtil; + private GlusterUtil glusterUtil; + + public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { + super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName + + " Rebalance", false, true, false); + setLayout(layout); + taskInfo.setName(getId()); + init(); + } + + private void init() { + ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); + serverUtil = ctx.getBean(ServerUtil.class); + glusterUtil = ctx.getBean(GlusterUtil.class); + } + + @Override + public String getId() { + return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); + } + + @Override + public void start() { + try { + serverName = getOnlineServer().getName(); + startRebalance(serverName); + } catch(ConnectionException e) { + // online server might have gone offline. try with a new one + serverName = getNewOnlineServer().getName(); + startRebalance(serverName); + } + } + + private void startRebalance(String serverName) { + String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; + String output = (String)serverUtil.executeOnServer(true, serverName, command, String.class); + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output))); + } + + @Override + public void resume() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public void stop() { + try { + glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); + } catch (ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + } + } + + @Override + public void pause() { + getTaskInfo().setStatus( + new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, + "Pause/Resume is not supported in Volume Rebalance"))); + } + + @Override + public TaskStatus checkStatus() { + try { + return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); + } catch(ConnectionException e) { + // online server might have gone offline. update the failure status + getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); + return getTaskInfo().getStatus(); + } + } + + public void setLayout(String layout) { + this.layout = layout; + } + + public String getLayout() { + return layout; + } + + @Override + public void commit() { + // TODO Auto-generated method stub + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java new file mode 100644 index 00000000..94c743aa --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java @@ -0,0 +1,154 @@ +/** + * ServerDiscoveryTask.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.gateway.tasks; + +import java.util.ArrayList; +import java.util.List; + +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.GlusterConstants; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.gateway.data.ClusterInfo; +import com.gluster.storage.management.gateway.data.PersistenceDao; +import com.gluster.storage.management.gateway.data.ServerInfo; +import com.gluster.storage.management.gateway.resources.v1_0.DiscoveredServersResource; +import com.gluster.storage.management.gateway.services.ClusterService; +import com.gluster.storage.management.gateway.services.GlusterServerService; +import com.gluster.storage.management.gateway.utils.ServerUtil; + +/** + * Task for syncing server details. This performs two things:
+ * 1. Auto-discovery of servers eligible to be added to the Gluster cluster.
+ * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user + * adds/removes servers manually using the CLI. + */ +@Component +public class ServerSyncTask { + private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private DiscoveredServersResource discoveredServersResource; + + @Autowired + private GlusterServerService glusterServerService; + + @Autowired + private String discoveryMechanism; + + @Autowired + private ClusterService clusterService; + + @Autowired + private PersistenceDao clusterDao; + + public void perform() { + discoverServers(); + syncClusterServerMapping(); + } + + private void syncClusterServerMapping() { + List clusters = clusterService.getAllClusters(); + for(ClusterInfo cluster : clusters) { + List servers = cluster.getServers(); + List actualServers = glusterServerService.getGlusterServers(cluster.getName(), false); + updateRemovedServers(cluster, servers, actualServers); + updateAddedServers(cluster, servers, actualServers); + } + } + + private void updateAddedServers(ClusterInfo cluster, List servers, List actualServers) { + List addedServers = findAddedServers(cluster.getName(), servers, actualServers); + for(String addedServer : addedServers) { + clusterService.mapServerToCluster(cluster.getName(), addedServer); + } + } + + private void updateRemovedServers(ClusterInfo cluster, List servers, List actualServers) { + List removedServers = findRemovedServers(servers, actualServers); + for(String removedServer : removedServers) { + clusterService.unmapServerFromCluster(cluster.getName(), removedServer); + } + } + + private List findRemovedServers(List servers, List actualServers) { + List removedServers = new ArrayList(); + + for(ServerInfo server : servers) { + if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { + removedServers.add(server.getName()); + } + } + return removedServers; + } + + private List findAddedServers(String clusterName, List servers, List actualServers) { + List addedServers = new ArrayList(); + for(GlusterServer actualServer : actualServers) { + if(!serverExists(servers, actualServer.getName())) { + addedServers.add(actualServer.getName()); + } + } + return addedServers; + } + + private boolean serverExists(List servers, String name) { + for(ServerInfo server : servers) { + if(server.getName().equalsIgnoreCase(name)) { + return true; + } + } + return false; + } + + @SuppressWarnings("unchecked") + private void discoverServers() { + if(discoveryMechanism.equals(GlusterConstants.NONE)) { + return; + } + + List serverNameList = new ArrayList(); + + ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList()); + if(result.isSuccess()) { + List existingServers = clusterDao.findBySQL("select name from server_info"); + String serverNames = result.getOutput(); + String[] parts = serverNames.split(CoreConstants.NEWLINE); + for(String serverName : parts) { + // The server discovery mechanism will return every server that has not been "peer probed". However we + // need to filter out those servers that are the "first" server of a new cluster, and hence are still + // not peer probed. + if(!existingServers.contains(serverName)) { + serverNameList.add(serverName); + } + } + } + + discoveredServersResource.setDiscoveredServerNames(serverNameList); + } +} \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/Task.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/Task.java new file mode 100644 index 00000000..1ba360bc --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/tasks/Task.java @@ -0,0 +1,112 @@ +/** + * Task.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.gateway.tasks; + +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.TaskInfo; +import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.gateway.services.ClusterService; + +public abstract class Task { + public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; + + protected TaskInfo taskInfo; + protected String clusterName; + private ClusterService clusterService; + + public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, + boolean canPause, boolean canStop, boolean canCommit) { + TaskInfo taskInfo = new TaskInfo(); + taskInfo.setType(type); + taskInfo.setReference(reference); + taskInfo.setDescription(desc); + taskInfo.setPauseSupported(canPause); + taskInfo.setStopSupported(canStop); + taskInfo.setCommitSupported(canCommit); + + init(clusterService, clusterName, taskInfo); + + } + + public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + init(clusterService, clusterName, taskInfo); + } + + private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { + this.clusterService = clusterService; + setClusterName(clusterName); + setTaskInfo(taskInfo); + } + + protected GlusterServer getOnlineServer() { + return clusterService.getOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer() { + return clusterService.getNewOnlineServer(clusterName); + } + + protected GlusterServer getNewOnlineServer(String exceptServerName) { + return clusterService.getNewOnlineServer(clusterName, exceptServerName); + } + + public String getTypeStr() { + return TASK_TYPE_STR[taskInfo.getType().ordinal()]; + } + + public TASK_TYPE getType() { + return getTaskInfo().getType(); + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public TaskInfo getTaskInfo() { + return taskInfo; + } + + public void setTaskInfo(TaskInfo info) { + this.taskInfo = info; + } + + public abstract String getId(); + + public abstract void start(); + + public abstract void resume(); + + public abstract void stop(); + + public abstract void pause(); + + public abstract void commit(); + + /** + * This method should check current status of the task and update it's taskInfo accordingly + */ + public abstract TaskStatus checkStatus(); +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java new file mode 100644 index 00000000..13a58729 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java @@ -0,0 +1,169 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.Status; + +/** + * + */ +@Component +public abstract class AbstractStatsFactory implements StatsFactory { + @Autowired + protected ServerUtil serverUtil; + + private Logger logger = Logger.getLogger(AbstractStatsFactory.class); + + protected ServerStats getFirstOnlineServerStats(List serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + try { + ServerStats stats = fetchStats(serverName, period); + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return stats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + int rowCount = aggregatedStats.getMetadata().getRowCount(); + int columnCount = aggregatedStats.getMetadata().getLegend().size(); + int[][] dataCount = initDataCountArray(rowCount, columnCount); + + for (String serverName : serverNames) { + try { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch performance stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + /** + * + * @param statsToBeAdded + * @param targetStats + * @param dataCount Each element of this matrix will be incremented for every valid element added + * @return + */ + protected List addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { + List serverStatsRows = statsToBeAdded.getRows(); + for (int rowNum = 0; rowNum < serverStatsRows.size() + && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { + ServerStatsRow row = serverStatsRows.get(rowNum); + List rowData = row.getUsageData(); + + List aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); + for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { + // Add the data + Double data = rowData.get(i); + if(!data.isNaN()) { + // data is available. add it. + aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); + // increment record count. this will be used for calculating average of aggregated data. + dataCount[rowNum][i]++; + } + } + } + return serverStatsRows; + } + + protected void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { + List rows = aggregatedStats.getRows(); + for(int rowNum = 0; rowNum < rows.size(); rowNum++) { + List data = rows.get(rowNum).getUsageData(); + for(int columnNum = 0; columnNum < data.size(); columnNum++) { + data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); + } + } + } + + protected int[][] initDataCountArray(int rowCount, int columnCount) { + int[][] dataCount = new int[rowCount][columnCount]; + // initialize all data counts to 1 + for(int rowNum = 0; rowNum < rowCount; rowNum++) { + for(int columnNum = 0; columnNum < columnCount; columnNum++) { + dataCount[rowNum][columnNum] = 1; + } + } + return dataCount; + } + + @Override + public ServerStats fetchAggregatedStats(List serverNames, String period) { + if(serverNames == null || serverNames.size() == 0) { + throw new GlusterRuntimeException("No server names passed to fetchAggregaredStats!"); + } + + ServerStats firstServerStats = getFirstOnlineServerStats(serverNames, period, true, true); + + ServerStats aggregatedStats = new ServerStats(firstServerStats); + aggregateStats(serverNames, aggregatedStats, period); + return aggregatedStats; + } + + @Override + public ServerStats fetchStats(String serverName, String period, String...args) { + String argsStr = ""; + for (String arg : args) { + if(arg != null) { + argsStr += " " + arg; + } + } + Object output = serverUtil.executeScriptOnServer(true, serverName, getStatsScriptName() + argsStr + " " + + period, ServerStats.class); + //String cpuUsageData = " 1310468100 300 1310471700 13 3 user system total 13104681002.23802952e-14.3747778209e-016.6128073384e-01 13104684002.3387347338e-014.4642717442e-016.8030064780e-01 13104687005.5043873220e+006.2462376636e+001.1750624986e+01 13104690002.4350593653e+012.6214585217e+015.0565178869e+01 13104693004.0786489953e+014.6784713828e+018.7571203781e+01 13104696004.1459955508e+015.2546309044e+019.4006264551e+01 13104699004.2312286165e+015.2390588332e+019.4702874497e+01 13104702004.2603794982e+015.1598861493e+019.4202656475e+01 13104705003.8238751290e+014.5312089966e+018.3550841256e+01 13104708001.7949961224e+012.1282058418e+013.9232019642e+01 13104711001.2330371421e-014.6347832868e-015.8678204289e-01 13104714001.6313260492e-015.4088119561e-017.0401380052e-01 1310471700NaNNaNNaN "; + //Object output = unmarshal(ServerStats.class, cpuUsageData, false); + if(output instanceof Status) { + throw new GlusterRuntimeException(((Status)output).toString()); + } + return (ServerStats) output; + } + + public abstract String getStatsScriptName(); +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java new file mode 100644 index 00000000..b6ef9ef2 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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.gateway.utils; + +import org.springframework.stereotype.Component; + +/** + * + */ +@Component +public class CpuStatsFactory extends AbstractStatsFactory { + + private static final String CPU_STATS_SCRIPT = "get_rrd_cpu_details.py"; + + @Override + public String getStatsScriptName() { + return CPU_STATS_SCRIPT; + } + +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java new file mode 100644 index 00000000..55909d54 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java @@ -0,0 +1,662 @@ +/** + * GlusterUtil.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.gateway.utils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.regex.Pattern; + +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.GlusterConstants; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Brick; +import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; +import com.gluster.storage.management.core.model.GlusterServer; +import com.gluster.storage.management.core.model.InitDiskStatusResponse; +import com.gluster.storage.management.core.model.InitDiskStatusResponse.FORMAT_STATUS; +import com.gluster.storage.management.core.model.Server.SERVER_STATUS; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.model.TaskStatus; +import com.gluster.storage.management.core.model.Volume; +import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; +import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; +import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; +import com.gluster.storage.management.core.utils.GlusterCoreUtil; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.StringUtil; +import com.gluster.storage.management.gateway.resources.v1_0.TasksResource; + +@Component +public class GlusterUtil { + private static final String glusterFSminVersion = "3.1"; + + private static final String HOSTNAME_PFX = "Hostname:"; + private static final String UUID_PFX = "Uuid:"; + private static final String STATE_PFX = "State:"; + private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; + + private static final String VOLUME_NAME_PFX = "Volume Name:"; + private static final String VOLUME_TYPE_PFX = "Type:"; + private static final String VOLUME_STATUS_PFX = "Status:"; + private static final String VOLUME_NUMBER_OF_BRICKS = "Number of Bricks:"; + private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; + private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; + private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; + private static final String VOLUME_OPTION_AUTH_ALLOW_PFX = "auth.allow:"; + private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; + private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; + private static final String VOLUME_TYPE_REPLICATE = "Replicate"; + private static final String GLUSTERD_INFO_FILE = "/etc/glusterd/glusterd.info"; + + private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); + + private static final String INITIALIZE_DISK_STATUS_SCRIPT = "get_format_device_status.py"; + + @Autowired + private SshUtil sshUtil; + + @Autowired + private ServerUtil serverUtil; + + @Autowired + private TasksResource taskResource; + + public void setSshUtil(SshUtil sshUtil) { + this.sshUtil = sshUtil; + } + + public SshUtil getSshUtil() { + return sshUtil; + } + + /** + * Extract value of given token from given line. It is assumed that the token, if present, will be of the following + * form: token: value + * + * @param line + * Line to be analyzed + * @param token + * Token whose value is to be extracted + * @return Value of the token, if present in the line + */ + private final String extractToken(String line, String token) { + if (line.contains(token)) { + return line.split(token)[1].trim(); + } + return null; + } + + public GlusterServer getGlusterServer(GlusterServer onlineServer, String serverName) { + List servers = getGlusterServers(onlineServer); + for (GlusterServer server : servers) { + if (server.getName().equals(serverName)) { + return server; + } + } + return null; + } + + private String getUuid(String serverName) { + ProcessResult result = getSshUtil().executeRemote(serverName, "cat " + GLUSTERD_INFO_FILE); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't read file [" + GLUSTERD_INFO_FILE + "]. Error: " + + result.toString()); + } + return result.getOutput().split("=")[1]; + } + + public List getGlusterServers(GlusterServer knownServer) { + String output = getPeerStatus(knownServer.getName()); + if (output == null) { + return null; + } + + knownServer.setUuid(getUuid(knownServer.getName())); + + List glusterServers = new ArrayList(); + glusterServers.add(knownServer); + + GlusterServer server = null; + boolean foundHost = false; + boolean foundUuid = false; + for (String line : output.split(CoreConstants.NEWLINE)) { + if (foundHost && foundUuid) { + // Host and UUID is found, we should look for state + String state = extractToken(line, STATE_PFX); + if (state != null) { + server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE + : SERVER_STATUS.OFFLINE); + // Completed populating current server. Add it to the list + // and reset all related variables. + glusterServers.add(server); + + foundHost = false; + foundUuid = false; + server = null; + } + } else if (foundHost) { + // Host is found, look for UUID + String uuid = extractToken(line, UUID_PFX); + if (uuid != null) { + server.setUuid(uuid); + foundUuid = true; + } + } else { + // Look for the next host + if (server == null) { + server = new GlusterServer(); + } + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + server.setName(hostName); + foundHost = true; + } + } + + } + return glusterServers; + } + + public List getGlusterServerNames(String knownServer) { + String output = getPeerStatus(knownServer); + if (output == null) { + return null; + } + + List glusterServerNames = new ArrayList(); + for (String line : output.split(CoreConstants.NEWLINE)) { + String hostName = extractToken(line, HOSTNAME_PFX); + if (hostName != null) { + glusterServerNames.add(hostName); + } + } + return glusterServerNames; + } + + /** + * @param knownServer + * A known server on which the gluster command will be executed to fetch peer status + * @return Outout of the "gluster peer status" command + */ + private String getPeerStatus(String knownServer) { + String output; + ProcessResult result = getSshUtil().executeRemote(knownServer, "gluster peer status"); + if (!result.isSuccess()) { + output = null; + } + output = result.getOutput(); + return output; + } + + public void addServer(String existingServer, String newServer) { + ProcessResult result = sshUtil.executeRemote(existingServer, "gluster peer probe " + newServer); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't probe server [" + newServer + "] from [" + existingServer + + "]. Error: " + result); + } + + // reverse peer probe to ensure that host names appear in peer status on both sides + result = sshUtil.executeRemote(newServer, "gluster peer probe " + existingServer); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't _reverse_ probe server [" + existingServer + "] from [" + + newServer + "]. Error: " + result); + } + } + + public Status startVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster volume start " + volumeName)); + } + + public Status stopVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume stop " + volumeName)); + } + + public void resetOptions(String volumeName, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't reset options for volume [" + volumeName + "]! Error: " + + result); + } + } + + public void createVolume(String knownServer, String volumeName, String volumeTypeStr, String transportTypeStr, + Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, String options) { + + int count = 1; // replica or stripe count + + VOLUME_TYPE volType = Volume.getVolumeTypeByStr(volumeTypeStr); + String volTypeArg = null; + if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volTypeArg = "replica"; + count = replicaCount; + } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volTypeArg = "stripe"; + count = stripeCount; + } + + String transportTypeArg = null; + TRANSPORT_TYPE transportType = Volume.getTransportTypeByStr(transportTypeStr); + transportTypeArg = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; + + String command = prepareVolumeCreateCommand(volumeName, StringUtil.extractList(bricks, ","), count, + volTypeArg, transportTypeArg); + ProcessResult result = sshUtil.executeRemote(knownServer, command); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Error in creating volume [" + volumeName + "]: " + result); + } + + try { + createOptions(volumeName, StringUtil.extractMap(options, ",", "="), knownServer); + } catch(Exception e) { + throw new GlusterRuntimeException( + "Volume created successfully, however following errors occurred while setting options: " + + CoreConstants.NEWLINE + e.getMessage()); + } + } + + private String prepareVolumeCreateCommand(String volumeName, List brickDirectories, int count, + String volumeType, String transportTypeStr) { + StringBuilder command = new StringBuilder("gluster volume create " + volumeName + " "); + if (volumeType != null) { + command.append(volumeType + " " + count + " "); + } + command.append("transport " + transportTypeStr); + for (String brickDir : brickDirectories) { + command.append(" " + brickDir); + } + return command.toString(); + } + + public void createOptions(String volumeName, Map options, String knownServer) { + String errors = ""; + if (options != null) { + for (Entry option : options.entrySet()) { + String key = option.getKey(); + String value = option.getValue(); + + try { + setOption(volumeName, key, value, knownServer); + } catch(Exception e) { + // append error + errors += e.getMessage() + CoreConstants.NEWLINE; + } + } + } + if (!errors.trim().isEmpty()) { + throw new GlusterRuntimeException("Errors while setting option(s) on volume [" + volumeName + "] : " + + errors.trim()); + } + } + + public void setOption(String volumeName, String key, String value, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " + + "\"" + value + "\""); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Volume [" + volumeName + "] set [" + key + "=" + value + "] => " + + result); + } + } + + public Status deleteVolume(String volumeName, String knownServer) { + return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume delete " + volumeName)); + } + + private String getVolumeInfo(String volumeName, String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info " + volumeName); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [gluster volume info " + volumeName + "] failed on [" + + knownServer + "] with error: " + result); + } + return result.getOutput(); + } + + private String getVolumeInfo(String knownServer) { + ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info "); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [gluster volume info] failed on [" + knownServer + + "] with error: " + result); + } + return result.getOutput(); + } + + private boolean readVolumeType(Volume volume, String line) { + String volumeType = extractToken(line, VOLUME_TYPE_PFX); + if (volumeType != null) { + if (volumeType.equals(VOLUME_TYPE_DISTRIBUTE)) { + volume.setVolumeType(VOLUME_TYPE.PLAIN_DISTRIBUTE); + } else if (volumeType.equals(VOLUME_TYPE_REPLICATE)) { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_MIRROR); + volume.setReplicaCount(Volume.DEFAULT_REPLICA_COUNT); + } else { + volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_STRIPE); + volume.setStripeCount(Volume.DEFAULT_STRIPE_COUNT); + } + return true; + } + return false; + } + + private void readReplicaOrStripeCount(Volume volume, String line) { + if (extractToken(line, "x") != null) { + // expected formated of line is "Number of Bricks: 3 x 2 = 6" + int count = Integer.parseInt(line.split("x")[1].split("=")[0].trim()); + if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { + volume.setStripeCount(count); + } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { + volume.setReplicaCount(count); + volume.setStripeCount(0); + } + + } + return; + } + + private boolean readVolumeStatus(Volume volume, String line) { + String volumeStatus = extractToken(line, VOLUME_STATUS_PFX); + if (volumeStatus != null) { + volume.setStatus(volumeStatus.equals("Started") ? VOLUME_STATUS.ONLINE : VOLUME_STATUS.OFFLINE); + return true; + } + return false; + } + + private boolean readTransportType(Volume volume, String line) { + String transportType = extractToken(line, VOLUME_TRANSPORT_TYPE_PFX); + if (transportType != null) { + volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET : TRANSPORT_TYPE.INFINIBAND); + return true; + } + return false; + } + + private boolean readBrick(Volume volume, String brickLine) { + BRICK_STATUS brickStatus; + if (brickLine.matches("Brick[0-9]+:.*")) { + // line: "Brick1: server1:/export/md0/volume-name" + String brickName = brickLine.split(": ")[1]; + String[] brickParts = brickLine.split(":"); + String serverName = brickParts[1].trim(); + String brickDir = brickParts[2].trim(); + //To get the brick status + brickStatus = getBrickStatus(serverName, volume.getName(), brickName); + + addBrickToVolume(volume, serverName, brickDir, brickStatus); + return true; + } + return false; + } + + private void addBrickToVolume(Volume volume, String serverName, String brickDir, BRICK_STATUS status) { + //If brick directory has standard path, find and assign device name otherwise null + String stdBrickDirPattern = "^/export/.*/.*"; // e.g: /export/sdb/test + String deviceName = null; + if (Pattern.matches(stdBrickDirPattern, brickDir) ) { + deviceName = brickDir.split("/")[2].trim(); + } + volume.addBrick(new Brick(serverName, status, deviceName, brickDir)); + } + + // Do not throw exception, Gracefully handle as Offline brick. + private BRICK_STATUS getBrickStatus(String serverName, String volumeName, String brick){ + try { + ProcessResult output = getSshUtil().executeRemote(serverName, "get_brick_status.py" + " " + volumeName + " " + brick); + + if (output.isSuccess() && output.getOutput().equals(CoreConstants.ONLINE)) { + return BRICK_STATUS.ONLINE; + } else { + return BRICK_STATUS.OFFLINE; + } + } catch(Exception e) { // Particularly interested on ConnectionExecption, if the server is offline + return BRICK_STATUS.OFFLINE; + } + } + + private boolean readBrickGroup(String line) { + return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; + } + + private boolean readOptionReconfigGroup(String line) { + return extractToken(line, VOLUME_OPTIONS_RECONFIG_PFX) != null; + } + + private boolean readOption(Volume volume, String line) { + if (line.matches("^[^:]*:.*$")) { + int index = line.indexOf(':'); + volume.setOption(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim()); + + if (line.substring(0, index).trim().equals(Volume.OPTION_NFS_DISABLE)) { + if (line.substring(index + 1, line.length()).trim().equals(GlusterConstants.ON)) { + volume.disableNFS(); + } else { + volume.enableNFS(); + } + } + + return true; + } + return false; + } + + public Volume getVolume(String volumeName, String knownServer) { + return parseVolumeInfo(getVolumeInfo(volumeName, knownServer)).get(0); + } + + public List getAllVolumes(String knownServer) { + return parseVolumeInfo(getVolumeInfo(knownServer)); + } + + private List parseVolumeInfo(String volumeInfoText) { + List volumes = new ArrayList(); + boolean isBricksGroupFound = false; + boolean isOptionReconfigFound = false; + Volume volume = null; + + for (String line : volumeInfoText.split(CoreConstants.NEWLINE)) { + String volumeName = extractToken(line, VOLUME_NAME_PFX); + if (volumeName != null) { + if (volume != null) { + volumes.add(volume); + } + + // prepare next volume to be read + volume = new Volume(); + volume.setName(volumeName); + isBricksGroupFound = isOptionReconfigFound = false; + continue; + } + + if (readVolumeType(volume, line)) + continue; + if (extractToken(line, VOLUME_NUMBER_OF_BRICKS) != null) { + readReplicaOrStripeCount(volume, line); + } + if (readVolumeStatus(volume, line)) + continue; + if (readTransportType(volume, line)) + continue; + if (readBrickGroup(line)) { + isBricksGroupFound = true; + continue; + } + + if (isBricksGroupFound) { + if (readBrick(volume, line)) { + continue; + } else { + isBricksGroupFound = false; + } + } + + if (readOptionReconfigGroup(line)) { + isOptionReconfigFound = true; + continue; + } + + if (isOptionReconfigFound) { + if (readOption(volume, line)) { + continue; + } else { + isOptionReconfigFound = false; + } + } + } + + if (volume != null) {// Adding the last volume parsed + volumes.add(volume); + } + + return volumes; + } + + public void addBricks(String volumeName, List bricks, String knownServer) { + StringBuilder command = new StringBuilder("gluster volume add-brick " + volumeName); + for (String brickDir : bricks) { + command.append(" " + brickDir); + } + + ProcessResult result = sshUtil.executeRemote(knownServer, command.toString()); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Error in volume [" + volumeName + "] add-brick [" + bricks + "]: " + + result); + } + } + + public String getLogLocation(String volumeName, String brickName, String knownServer) { + String command = "gluster volume log locate " + volumeName + " " + brickName; + ProcessResult result = sshUtil.executeRemote(knownServer, command); + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [" + command + "] failed with error: [" + result.getExitValue() + + "][" + result.getOutput() + "]"); + } + String output = result.getOutput(); + if (output.startsWith(VOLUME_LOG_LOCATION_PFX)) { + return output.substring(VOLUME_LOG_LOCATION_PFX.length()).trim(); + } + + throw new GlusterRuntimeException("Couldn't parse output of command [" + command + "]. Output [" + output + + "] doesn't start with prefix [" + VOLUME_LOG_LOCATION_PFX + "]"); + } + + public String getLogFileNameForBrickDir(String brickDir) { + String logFileName = brickDir; + if (logFileName.startsWith(File.separator)) { + logFileName = logFileName.replaceFirst(File.separator, ""); + } + logFileName = logFileName.replaceAll(File.separator, "-") + ".log"; + return logFileName; + } + + public Status removeBricks(String volumeName, List bricks, String knownServer) { + StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName); + for (String brickDir : bricks) { + command.append(" " + brickDir); + } + return new Status(sshUtil.executeRemote(knownServer, command.toString())); + } + + public void removeServer(String existingServer, String serverName) { + ProcessResult result = sshUtil.executeRemote(existingServer, "gluster --mode=script peer detach " + serverName); + if(!result.isSuccess()) { + throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); + } + } + + public TaskStatus checkRebalanceStatus(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " status"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + if (processResult.getOutput().trim().matches("^rebalance completed.*")) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if(processResult.getOutput().trim().matches(".*in progress.*")) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + } else { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + taskStatus.setMessage(processResult.getOutput()); // Common + return taskStatus; + } + + public void stopRebalance(String serverName, String volumeName) { + String command = "gluster volume rebalance " + volumeName + " stop"; + ProcessResult processResult = sshUtil.executeRemote(serverName, command); + TaskStatus taskStatus = new TaskStatus(); + if (processResult.isSuccess()) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + taskStatus.setMessage(processResult.getOutput()); + } + } + + public TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { + Object response = serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " + + diskName, InitDiskStatusResponse.class); + + TaskStatus taskStatus = new TaskStatus(); + if (response instanceof Status) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + taskStatus.setMessage(((Status) response).getMessage()); + throw new GlusterRuntimeException(((Status) response).getMessage()); + } + + InitDiskStatusResponse initDiskStatusResponse = (InitDiskStatusResponse) response; + + if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.COMPLETED) { + taskStatus.setCode(Status.STATUS_CODE_SUCCESS); + } else if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.IN_PROGRESS) { + taskStatus.setCode(Status.STATUS_CODE_RUNNING); + taskStatus.setPercentCompleted(Math.round(initDiskStatusResponse.getCompletedBlocks() + / initDiskStatusResponse.getTotalBlocks() * 100)); + } else if(initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.NOT_RUNNING) { + taskStatus.setCode(Status.STATUS_CODE_FAILURE); + } + + taskStatus.setMessage(initDiskStatusResponse.getMessage()); + return taskStatus; + } + + public ProcessResult executeBrickMigration(String onlineServerName, String volumeName, String fromBrick, + String toBrick, String operation) { + String command = "gluster volume replace-brick " + volumeName + " " + fromBrick + " " + toBrick + " " + operation; + ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); + if (!processResult.isSuccess()) { + throw new GlusterRuntimeException(processResult.toString()); + } + return processResult; + } + + public static void main(String args[]) { + // List names = new GlusterUtil().getGlusterServerNames(); + // System.out.println(names); + List disks = new ArrayList(); + disks.add("server1:sda"); + disks.add("server1:sdb"); + new GlusterUtil().addBricks("Volume3", disks, "localhost"); + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java new file mode 100644 index 00000000..dc88bf52 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java @@ -0,0 +1,68 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; + +/** + * + */ +@Component +public class MemoryStatsFactory extends AbstractStatsFactory { + + private static final String MEM_STATS_SCRIPT = "get_rrd_memory_details.py"; + + @Override + public String getStatsScriptName() { + return MEM_STATS_SCRIPT; + } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // stats returned by rrd script contains five columns - user, free, cache, buffer, total + // out of this, the "user" memory includes cached and buffer. We remove them to get the + // actual memory used by "user" + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + Double user = data.get(0); + Double free = data.get(1); + Double cache = data.get(2); + Double buffer = data.get(3); + Double total = data.get(4); + + Double actualUser = user - cache - buffer; + + // convert all figures from bytes to percentages + data.set(0, (actualUser * 100) / total); + data.set(1, (free * 100) / total); + data.set(2, (cache * 100) / total); + data.set(3, (buffer * 100) / total); + data.set(4, (total * 100) / total); + } + + return stats; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java new file mode 100644 index 00000000..d3d47c58 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.NetworkInterface; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; + +/** + * + */ +@Component +public class NetworkStatsFactory extends AbstractStatsFactory { + private static final Logger logger = Logger.getLogger(NetworkStatsFactory.class); + private static final String NETWORK_STATS_SCRIPT = "get_rrd_net_details.py"; + private int[][] dataCount; + + @Override + public String getStatsScriptName() { + return NETWORK_STATS_SCRIPT; + } + + @Override + protected ServerStats getFirstOnlineServerStats(List serverNames, String period, + boolean removeServerOnError, boolean removeOnlineServer) { + ServerStats firstOnlineServerStats = null; + for(int i = serverNames.size() - 1; i >= 0; i--) { + String serverName = serverNames.get(i); + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + try { + for(NetworkInterface networkInterface : server.getNetworkInterfaces()) { + ServerStats stats = fetchStats(serverName, period, networkInterface.getName()); + if(firstOnlineServerStats == null) { + firstOnlineServerStats = stats; + int rowCount = firstOnlineServerStats.getMetadata().getRowCount(); + int columnCount = firstOnlineServerStats.getMetadata().getLegend().size(); + dataCount = initDataCountArray(rowCount, columnCount); + } else { + addServerStats(stats, firstOnlineServerStats, dataCount); + } + } + + if(removeOnlineServer) { + serverNames.remove(serverName); + } + return firstOnlineServerStats; + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); + if(removeServerOnError) { + serverNames.remove(serverName); + } + continue; + } + } + throw new GlusterRuntimeException("All servers offline!"); + } + + protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { + if(serverNames.isEmpty()) { + return; + } + + for (String serverName : serverNames) { + try { + Server server = new Server(serverName); + serverUtil.fetchServerDetails(server); + + for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { + // fetch the stats and add to aggregated stats + addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); + } + } catch(Exception e) { + // server might be offline - continue with next one + logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); + continue; + } + } + + averageAggregatedStats(aggregatedStats, dataCount); + } + + @Override + public ServerStats fetchStats(String serverName, String period, String... args) { + ServerStats stats = super.fetchStats(serverName, period, args); + + // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s + int step = stats.getMetadata().getStep(); + for(ServerStatsRow row : stats.getRows()) { + List data = row.getUsageData(); + for (int i = 0; i < data.size(); i++) { + Double val = data.get(i); + data.set(i, val / 1024 / step); + } + } + + return stats; + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java new file mode 100644 index 00000000..91c7c81c --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/ServerUtil.java @@ -0,0 +1,286 @@ +/** + * ServerUtil.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.gateway.utils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.model.Server; +import com.gluster.storage.management.core.model.ServerStats; +import com.gluster.storage.management.core.model.ServerStatsRow; +import com.gluster.storage.management.core.model.Status; +import com.gluster.storage.management.core.response.GenericResponse; +import com.gluster.storage.management.core.utils.ProcessResult; +import com.gluster.storage.management.core.utils.ProcessUtil; + +@Component +public class ServerUtil { + @Autowired + ServletContext servletContext; + + @Autowired + private SshUtil sshUtil; + + @Autowired + private String appVersion; + + private static final Logger logger = Logger.getLogger(ServerUtil.class); + + private static final String SCRIPT_DIR = "scripts"; + private static final String SCRIPT_COMMAND = "python"; + private static final String REMOTE_SCRIPT_GET_DISK_FOR_DIR = "get_disk_for_dir.py"; + private static final String REMOTE_SCRIPT_GET_SERVER_DETAILS = "get_server_details.py"; + private static final String REMOTE_SCRIPT_BASE_DIR = "/opt/glustermg"; + private static final String REMOTE_SCRIPT_DIR_NAME = "backend"; + + public void setSshUtil(SshUtil sshUtil) { + this.sshUtil = sshUtil; + } + + public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List arguments) { + List command = new ArrayList(); + + command.add(SCRIPT_COMMAND); + command.add(getScriptPath(scriptName)); + command.addAll(arguments); + return new ProcessUtil().executeCommand(runInForeground, command); + } + + private String getScriptPath(String scriptName) { + return servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; + } + + private String getRemoteScriptDir() { + return REMOTE_SCRIPT_BASE_DIR + File.separator + appVersion + File.separator + REMOTE_SCRIPT_DIR_NAME; + } + + /** + * Fetch details of the given server. The server name must be populated in the object before calling this method. + * + * @param server + * Server whose details are to be fetched + */ + public void fetchServerDetails(Server server) { + Object response = fetchServerDetails(server.getName()); + server.copyFrom((Server) response); // Update the details in object + server.setDisks(((Server) response).getDisks()); + } + + public String fetchHostName(String serverName) { + Object response = fetchServerDetails(serverName); + return ((Server) response).getName(); + } + + private Object fetchServerDetails(String serverName) { + // fetch standard server details like cpu, disk, memory details + Object response = executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); + if (response instanceof Status) { + throw new GlusterRuntimeException(((Status) response).getMessage()); + } + return response; + } + + /** + * Executes given script on given server. Since the remote server may contain multiple versions of backend, this + * method will invoke the script present in directory of same version as the gateway. + * + * @param runInForeground + * @param serverName + * @param scriptWithArgs + * The script name followed by arguments to be passed. Note that the script name should not contain path + * as it will be automatically identified by the method. + * @param expectedClass + * Class of the object expected from script execution + * @return Object of the expected class from remote execution of the command. In case the remote execution fails + * ungracefully, an object of class {@link Status} will be returned. + */ + public Object executeScriptOnServer(boolean runInForeground, String serverName, String scriptWithArgs, + @SuppressWarnings("rawtypes") Class expectedClass) { + return executeOnServer(runInForeground, serverName, getRemoteScriptDir() + File.separator + scriptWithArgs, expectedClass); + } + + /** + * Executes given command on given server + * + * @param runInForeground + * @param serverName + * @param commandWithArgs + * @param expectedClass + * Class of the object expected from script execution + * @return Object of the expected class from remote execution of the command. In case the remote execution fails + * ungracefully, an object of class {@link Status} will be returned. + */ + @SuppressWarnings("rawtypes") + public Object executeOnServer(boolean runInForeground, String serverName, String commandWithArgs, + Class expectedClass) { + try { + String output = executeOnServer(serverName, commandWithArgs); + + // In case the script execution exits ungracefully, the agent would return a GenericResponse. + // hence pass last argument as true to try GenericResponse unmarshalling in such cases. + Object response = unmarshal(expectedClass, output, expectedClass != GenericResponse.class); + if (expectedClass != GenericResponse.class && response instanceof GenericResponse) { + // expected class was not GenericResponse, but that's what we got. This means the + // script failed ungracefully. Extract and return the status object from the response + return ((GenericResponse) response).getStatus(); + } + return response; + } catch (RuntimeException e) { + // Except for connection exception, wrap any other exception in the a object and return it. + if (e instanceof ConnectionException) { + throw e; + } else { + // error during unmarshalling. return status with error from exception. + return new Status(e); + } + } + } + + private String executeOnServer(String serverName, String commandWithArgs) { + ProcessResult result = sshUtil.executeRemote(serverName, commandWithArgs); + + if (!result.isSuccess()) { + throw new GlusterRuntimeException("Command [" + commandWithArgs + "] failed on [" + serverName + + "] with error [" + result.getExitValue() + "][" + result.getOutput() + "]"); + } + return result.getOutput(); + } + + // This is the old executeOnServer that used socket communication. + // We can keep it commented for the time being. + // private String executeOnServerUsingSocket(String serverName, String commandWithArgs) { + // try { + // InetAddress address = InetAddress.getByName(serverName); + // Socket connection = new Socket(address, 50000); + // + // PrintWriter writer = new PrintWriter(connection.getOutputStream(), true); + // writer.println(commandWithArgs); + // writer.println(); // empty line means end of request + // + // InputStream inputStream = connection.getInputStream(); + // int available = inputStream.available(); + // + // StringBuffer output = new StringBuffer(); + // if( available > 0 ) { + // // This happens when PeerAgent sends complete file + // byte[] responseData = new byte[available]; + // inputStream.read(responseData); + // output.append(new String(responseData, "UTF-8")); + // } else { + // // This happens in case of normal XML response from PeerAgent + // BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); + // + // String line; + // while (!(line = reader.readLine()).trim().isEmpty()) { + // output.append(line + CoreConstants.NEWLINE); + // } + // } + // connection.close(); + // + // return output.toString(); + // } catch (Exception e) { + // throw new GlusterRuntimeException("Error during remote execution: [" + e.getMessage() + "]"); + // } + // } + + public void getFileFromServer(String serverName, String remoteFileName, String localDirName) { + sshUtil.getFile(serverName, remoteFileName, localDirName); + } + + /** + * Unmarshals given input string into object of given class + * + * @param expectedClass + * Class whose object is expected + * @param input + * Input string + * @param tryGenericResponseOnFailure + * If true, and if the unmarshalling fails for given class, another unmarshalling will be attempted with + * class {@link GenericResponse}. If this also fails, a status object with exception message is created + * and returned. + * @return Object of given expected class, or a status object in case first unmarshalling fails. + */ + @SuppressWarnings("rawtypes") + private Object unmarshal(Class expectedClass, String input, boolean tryGenericResponseOnFailure) { + try { + // create JAXB context and instantiate marshaller + JAXBContext context = JAXBContext.newInstance(expectedClass); + Unmarshaller um = context.createUnmarshaller(); + return um.unmarshal(new ByteArrayInputStream(input.getBytes())); + } catch (JAXBException e) { + if (tryGenericResponseOnFailure) { + // unmarshalling failed. try to unmarshal a GenericResponse object + return unmarshal(GenericResponse.class, input, false); + + } + return new Status(Status.STATUS_CODE_FAILURE, "Error during unmarshalling string [" + input + + "] for class [" + expectedClass.getName() + ": [" + e.getMessage() + "]"); + } + } + + /** + * @param serverName + * Server on which the directory is present + * @param brickDir + * Directory whose disk is to be fetched + * @return Status object containing the disk name, or error message in case the remote script fails. + */ + public Status getDiskForDir(String serverName, String brickDir) { + return (Status) executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); + } + + public static void main(String[] args) { +// ServerStats stats = new ServerUtil().fetchCPUUsageData("s1", "1d"); +// for(ServerStatsRow row : stats.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// JAXBContext context; +// try { +// context = JAXBContext.newInstance(ServerStats.class); +// Marshaller m = context.createMarshaller(); +// ByteArrayOutputStream out = new ByteArrayOutputStream(); +// m.marshal(stats, out); +// ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); +// for(ServerStatsRow row : stats1.getRows()) { +// System.out.println(row.getUsageData().get(2)); +// } +// } catch (JAXBException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java new file mode 100644 index 00000000..39dd42f9 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/SshUtil.java @@ -0,0 +1,388 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Arrays; + +import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import ch.ethz.ssh2.ChannelCondition; +import ch.ethz.ssh2.Connection; +import ch.ethz.ssh2.SCPClient; +import ch.ethz.ssh2.Session; +import ch.ethz.ssh2.StreamGobbler; + +import com.gluster.storage.management.core.constants.CoreConstants; +import com.gluster.storage.management.core.exceptions.ConnectionException; +import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; +import com.gluster.storage.management.core.utils.FileUtil; +import com.gluster.storage.management.core.utils.LRUCache; +import com.gluster.storage.management.core.utils.ProcessResult; + +/** + * + */ +@Component +public class SshUtil { + private static final String TEMP_DIR = "/tmp/"; + public static final String SSH_AUTHORIZED_KEYS_DIR_LOCAL = "/opt/glustermg/keys/"; + public static final String SSH_AUTHORIZED_KEYS_DIR_REMOTE = "/root/.ssh/"; + private static final String SSH_AUTHORIZED_KEYS_FILE = "authorized_keys"; + private static final String SSH_AUTHORIZED_KEYS_PATH_REMOTE = SSH_AUTHORIZED_KEYS_DIR_REMOTE + SSH_AUTHORIZED_KEYS_FILE; + public static final File PRIVATE_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa"); + public static final File PUBLIC_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa.pub"); +// private static final String SCRIPT_DISABLE_SSH_PASSWORD_AUTH = "disable-ssh-password-auth.sh"; + private static final String PRIVATE_KEY_PASSPHRASE = "gluster"; + private LRUCache sshConnCache = new LRUCache(10); + + // TODO: Make user name configurable + private static final String USER_NAME = "root"; + // TODO: Make default password configurable + private static final String DEFAULT_PASSWORD = "syst3m"; + + private static final Logger logger = Logger.getLogger(SshUtil.class); + + @Autowired + private Integer sshConnectTimeout; + @Autowired + private Integer sshKexTimeout; + @Autowired + private Integer sshExecTimeout; + + public boolean hasDefaultPassword(String serverName) { + try { + getConnectionWithPassword(serverName); + return true; + } catch(ConnectionException e) { + return false; + } + } + + public boolean isPublicKeyInstalled(String serverName) { + try { + getConnection(serverName); + return true; + } catch(ConnectionException e) { + return false; + } + } + + public void getFile(String serverName, String remoteFile, String localDir) { + try { + Connection conn = getConnection(serverName); + SCPClient scpClient = new SCPClient(conn); + scpClient.get(remoteFile, localDir); + } catch (IOException e) { + throw new GlusterRuntimeException("Error while fetching file [" + remoteFile + "] from server [" + + serverName + "]", e); + } + } + + public synchronized void installPublicKey(String serverName) { + Connection conn = getConnectionWithPassword(serverName); + SCPClient scpClient = new SCPClient(conn); + + // delete file if it exists + File localTempFile = new File(TEMP_DIR + SSH_AUTHORIZED_KEYS_FILE); + if(localTempFile.exists()) { + localTempFile.delete(); + } + try { + // get authorized_keys from server + scpClient.get(SSH_AUTHORIZED_KEYS_PATH_REMOTE, TEMP_DIR); + } catch (IOException e) { + // file doesn't exist. it will get created. + } + + byte[] publicKeyData; + try { + publicKeyData = FileUtil.readFileAsByteArray(PUBLIC_KEY_FILE); + } catch (Exception e) { + throw new GlusterRuntimeException("Couldn't load public key file [" + PUBLIC_KEY_FILE + "]", e); + } + + try { + // append it + FileOutputStream outputStream = new FileOutputStream(localTempFile, true); + outputStream.write(CoreConstants.NEWLINE.getBytes()); + outputStream.write(publicKeyData); + outputStream.close(); + } catch (Exception e) { + throw new GlusterRuntimeException("Couldnt append file [" + localTempFile + "] with public key!", e); + } + + try { + scpClient.put(localTempFile.getAbsolutePath(), SSH_AUTHORIZED_KEYS_FILE, SSH_AUTHORIZED_KEYS_DIR_REMOTE, "0600"); + } catch (IOException e) { + throw new GlusterRuntimeException("Couldn't add public key to server [" + serverName + "]", e); + } + + // It was decided NOT to disable password login as this may not be acceptable in a bare-metal environment + // disableSshPasswordLogin(serverName, scpClient); + } + +// private void disableSshPasswordLogin(String serverName, SCPClient scpClient) { +// ProcessResult result = executeRemote(serverName, SCRIPT_DISABLE_SSH_PASSWORD_AUTH); +// if(!result.isSuccess()) { +// throw new GlusterRuntimeException("Couldn't disable SSH password authentication on [" + serverName +// + "]. Error: " + result); +// } +// } + + private Connection getConnectionWithPassword(String serverName) { + Connection conn = createConnection(serverName); + authenticateWithPassword(conn); + return conn; + } + + private synchronized Connection getConnection(String serverName) { + Connection conn = sshConnCache.get(serverName); + if (conn != null) { + return conn; + } + + conn = createConnection(serverName); + authenticateWithPublicKey(conn); + sshConnCache.put(serverName, conn); + return conn; + } + + private void authenticateWithPublicKey(Connection conn) { + try { + if (!supportsPublicKeyAuthentication(conn)) { + throw new ConnectionException("Public key authentication not supported on [" + conn.getHostname() + + "]"); + } + + if (!conn.authenticateWithPublicKey(USER_NAME, PRIVATE_KEY_FILE, PRIVATE_KEY_PASSPHRASE)) { + throw new ConnectionException("SSH Authentication (public key) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new ConnectionException("Exception during SSH authentication (public key) for server [" + + conn.getHostname() + "]", e); + } + } + + private void authenticateWithPassword(Connection conn) { + try { + if (!supportsPasswordAuthentication(conn)) { + throw new ConnectionException("Password authentication not supported on [" + conn.getHostname() + + "]"); + } + + if (!conn.authenticateWithPassword(USER_NAME, DEFAULT_PASSWORD)) { + throw new ConnectionException("SSH Authentication (password) failed for server [" + + conn.getHostname() + "]"); + } + } catch (IOException e) { + e.printStackTrace(); + throw new ConnectionException("Exception during SSH authentication (password) for server [" + + conn.getHostname() + "]", e); + } + } + + private boolean supportsPasswordAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("password"); + } + + private boolean supportsPublicKeyAuthentication(Connection conn) throws IOException { + return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("publickey"); + } + + private Connection createConnection(String serverName) { + Connection conn; + conn = new Connection(serverName); + try { + conn.connect(null, sshConnectTimeout, sshKexTimeout); + } catch (IOException e) { + logger.error("Couldn't establish SSH connection with server [" + serverName + "]", e); + throw new ConnectionException("Exception while creating SSH connection with server [" + serverName + "]", e); + } + return conn; + } + + private boolean wasTerminated(int condition) { + return ((condition | ChannelCondition.EXIT_SIGNAL) == condition); + } + + private boolean hasErrors(int condition, Session session) { + return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session))); + } + + private boolean timedOut(int condition) { + return (condition == ChannelCondition.TIMEOUT); + } + + private boolean exitedWithError(Session session) { + return session.getExitStatus() != ProcessResult.SUCCESS; + } + + private boolean exitedGracefully(int condition) { + return (condition | ChannelCondition.EXIT_STATUS) == condition; + } + + private boolean hasErrorStream(int condition) { + return (condition | ChannelCondition.STDERR_DATA) == condition; + } + + private ProcessResult executeCommand(Connection sshConnection, String command) { + try { + Session session = sshConnection.openSession(); + BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStdout()))); + BufferedReader stderrReader = new BufferedReader(new InputStreamReader(new StreamGobbler( + session.getStderr()))); + session.execCommand(command); + ProcessResult result = getResultOfExecution(session, stdoutReader, stderrReader); + session.close(); + return result; + } catch (IOException e) { + String errMsg = "Exception while executing command [" + command + "] on [" + sshConnection.getHostname() + + "]"; + logger.error(errMsg, e); + throw new GlusterRuntimeException(errMsg, e); + } + } + + private ProcessResult getResultOfExecution(Session session, BufferedReader stdoutReader, BufferedReader stderrReader) { + // Wait for program to come out either + // a) gracefully with an exit status, OR + // b) because of a termination signal + // c) command takes to long to exit (timeout) + int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, + sshExecTimeout); + StringBuilder output = new StringBuilder(); + + try { + if(!timedOut(condition)) { + readFromStream(stdoutReader, output); + if (hasErrors(condition, session)) { + readFromStream(stderrReader, output); + } + } + + return prepareProcessResult(session, condition, output.toString().trim()); + } catch (IOException e) { + String errMsg = "Error while reading output stream from SSH connection!"; + logger.error(errMsg, e); + return new ProcessResult(ProcessResult.FAILURE, errMsg); + } + } + + private ProcessResult prepareProcessResult(Session session, int condition, String output) { + ProcessResult result = null; + + if (wasTerminated(condition)) { + result = new ProcessResult(ProcessResult.FAILURE, output); + } else if (timedOut(condition)) { + result = new ProcessResult(ProcessResult.FAILURE, "Command timed out!"); + } else if (hasErrors(condition, session)) { + Integer exitStatus = session.getExitStatus(); + int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus); + result = new ProcessResult(statusCode, output); + } else { + result = new ProcessResult(ProcessResult.SUCCESS, output); + } + + return result; + } + + private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException { + while (true) { + String line = streamReader.readLine(); + if (line == null) { + break; + } + output.append(line + CoreConstants.NEWLINE); + } + } + + /** + * Executes given command on remote machine using password authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemoteWithPassword(String serverName, String command) { + return executeCommand(getConnectionWithPassword(serverName), command); + } + + private ProcessResult executeRemoteWithPubKey(String serverName, String command) { + try { + return executeCommand(getConnection(serverName), command); + } catch(GlusterRuntimeException e) { + Throwable cause = e.getCause(); + if(cause != null && cause instanceof IOException) { + // cached ssh connection might have gone bad. + // remove it and try with a new one + sshConnCache.remove(serverName); + return executeCommand(getConnection(serverName), command); + } else { + throw e; + } + } + } + + /** + * Executes given command on remote machine using public key authentication + * + * @param serverName + * @param command + * @return Result of remote execution + */ + public ProcessResult executeRemote(String serverName, String command) { + try { + return executeRemoteWithPubKey(serverName, command); + } catch(ConnectionException e) { + // Couldn't connect with public key. Try with default password. + return executeRemoteWithPassword(serverName, command); + } + } + + /** + * Checks if public key of management gateway is configured on given server + * + * @param serverName + * @return true if public key is configured, else false + */ + public boolean isPublicKeySetup(String serverName) { + try { + getConnection(serverName); + return true; + } catch (Exception e) { + return false; + } + } + + public void cleanup() { + for (Connection conn : sshConnCache.values()) { + conn.close(); + } + } +} diff --git a/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/StatsFactory.java b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/StatsFactory.java new file mode 100644 index 00000000..09851367 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/com/gluster/storage/management/gateway/utils/StatsFactory.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.gateway.utils; + +import java.util.List; + +import com.gluster.storage.management.core.model.ServerStats; + +/** + * + */ +public interface StatsFactory { + public ServerStats fetchStats(String serverName, String period, String...args); + public ServerStats fetchAggregatedStats(List serverName, String period); +} diff --git a/src/com.gluster.storage.management.gateway/src/log4j.properties b/src/com.gluster.storage.management.gateway/src/log4j.properties new file mode 100644 index 00000000..18e2e8b1 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/log4j.properties @@ -0,0 +1,19 @@ +log4j.rootLogger=INFO, CONSOLE + +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.immediateFlush=true +log4j.appender.CONSOLE.target=System.out +log4j.appender.CONSOLE.threshold=DEBUG +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d{dd MMM, yyyy HH:mm:ss} %p: %c %t - %m%n + +log4j.appender.R=org.apache.log4j.RollingFileAppender +log4j.appender.R.File=/var/log/glustermg/glustermg.log +log4j.appender.R.MaxFileSize=10MB +log4j.appender.R.MaxBackupIndex=10 +log4j.appender.R.layout=org.apache.log4j.PatternLayout +log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n + +log4j.logger.org=ERROR +log4j.logger.com=ERROR +log4j.logger.com.gluster=DEBUG \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.gateway/src/spring/gluster-server-base.xml new file mode 100644 index 00000000..c89eb2f0 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/spring/gluster-server-base.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + com.gluster.storage.management.gateway.data.ClusterInfo + + + + + + com.gluster.storage.management.gateway.data.ServerInfo + + + + + + + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.gateway/src/spring/gluster-server-security.xml b/src/com.gluster.storage.management.gateway/src/spring/gluster-server-security.xml new file mode 100644 index 00000000..abcd8c05 --- /dev/null +++ b/src/com.gluster.storage.management.gateway/src/spring/gluster-server-security.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com.gluster.storage.management.server.scripts/.project b/src/com.gluster.storage.management.server.scripts/.project deleted file mode 100644 index 110db62b..00000000 --- a/src/com.gluster.storage.management.server.scripts/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - com.gluster.storage.management.gateway.scripts - - - - - - org.python.pydev.PyDevBuilder - - - - - - org.python.pydev.pythonNature - - diff --git a/src/com.gluster.storage.management.server.scripts/.pydevproject b/src/com.gluster.storage.management.server.scripts/.pydevproject deleted file mode 100644 index c327cd69..00000000 --- a/src/com.gluster.storage.management.server.scripts/.pydevproject +++ /dev/null @@ -1,10 +0,0 @@ - - - - -Default -python 3.0 - -/com.gluster.storage.management.gateway.scripts/src - - diff --git a/src/com.gluster.storage.management.server.scripts/src/Commands.py b/src/com.gluster.storage.management.server.scripts/src/Commands.py deleted file mode 100644 index c728b565..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Commands.py +++ /dev/null @@ -1,78 +0,0 @@ -COMMAND_CREATE_VOLUME = "create-volume" -COMMAND_DELETE_VOLUME = "delete-volume" -COMMAND_START_VOLUME = "start-volume" -COMMAND_STOP_VOLUME = "stop-volume" -COMMAND_GET_VOLUME_HEALTH_STATUS = "get-volume-health-status" -COMMAND_GET_VOLUME_LIST = "get-volume-list" -COMMAND_GET_VOLUME_LOG = "get-volume-log" -COMMAND_CLEAR_VOLUME_LOGS = "clear-volume-logs" -COMMAND_GET_VOLUME_PROPERTY = "get-volume-property" -COMMAND_SET_VOLUME_PROPERTY = "set-volume-property" -COMMAND_GET_VOLUME_STATUS = "get-volume-status" -COMMAND_DOWNLOAD_VOLUME_LOGS = "download-volume-logs" -COMMAND_DELETE_SERVER = "delete-server" -COMMAND_GET_SERVER_DATE = "get-server-date" -COMMAND_GET_SERVER_VERSION_INFO = "get-server-version-info" -COMMAND_GET_INSTALLER_INFO = "get-installer-info" -COMMAND_GET_SERVER_LIST = "get-server-list" -COMMAND_GET_SERVER_SERVICE_STATUS = "get-server-service-status" -COMMAND_GET_STORAGE_SERVER_POOL_INFO = "get-storage-server-pool-info" -COMMAND_INSTALL_SERVER_BACKGROUND = "install-server-background" -COMMAND_PREPARE_DATA_DISK_BACKGROUND = "prepare-data-disk-background" -COMMAND_SET_SERVER_DATE = "set-server-date" -COMMAND_SET_SERVER_NETWORK_CONFIG = "set-server-network-config" -COMMAND_SET_STORAGE_SERVER_POOL_INFO = "set-storage-server-pool-info" -COMMAND_GET_SERVER_NETWORK_CONFIG = "get-server-network-config" -COMMAND_INSTALL_SERVER_STATUS = "install-server-status" -COMMAND_GET_SERVER_DISK_LIST = "get-server-disk-list" -COMMAND_PREPARE_DATA_DISK_STATUS = "prepare-data-disk-status" -COMMAND_GET_SERVER_SYSTEM_RESOURCE = "get-server-system-resource" -COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" -COMMAND_RUN_SERVER_SERVICE = "run-server-service" -COMMAND_SHUTDOWN_SERVER = "shutdown-server" -COMMAND_GET_SERVER_STATUS = "get-server-status" -COMMAND_GET_SERVER_LOG = "get-server-log" -COMMAND_DOWNLOAD_SERVER_LOGS = "download-server-logs" -COMMAND_CLEAR_SERVER_LOGS = "clear-server-logs" -COMMAND_GET_SERVER_RESOURCE_RRD = "get-server-resource-rrd" -COMMAND_GET_GSN_USER_INFO = "get-gsn-user-info" -COMMAND_SET_GSN_USER_INFO = "set-gsn-user-info" -COMMAND_GET_GLUSTER_UPDATE_INFO = "get-gluster-update-info" -COMMAND_DOWNLOAD_GLUSTER_UPDATE_BACKGROUND = "download-gluster-update-background" -COMMAND_DOWNLOAD_GLUSTER_UPDATE_STATUS = "download-gluster-update-status" -COMMAND_INSTALL_GLUSTER_UPDATE = "install-gluster-update" -COMMAND_EXPORT_CONFIG = "export-config" -COMMAND_IMPORT_CONFIG = "import-config" -COMMAND_SET_SYSTEM_PASSWORD = "set-system-password" -COMMAND_GET_SERVER_VOLUME_LIST = "get-server-volume-list" -COMMAND_RECONFIGURE_VOLUME = "reconfigure-volume" -COMMAND_SET_SERVER_DIRECTORY_SERVICE_CONFIG = "set-server-directory-service-config" -COMMAND_GET_SERVER_DIRECTORY_SERVICE_CONFIG = "get-server-directory-service-config" -COMMAND_JOIN_SERVER_TO_DIRECTORY_SERVICE = "join-server-to-directory-service" -COMMAND_SET_SERVER_TIME_CONFIG = "set-server-time-config" -COMMAND_GET_SERVER_TIME_CONFIG = "get-server-time-config" -COMMAND_LOGIN = "login" -COMMAND_LOGOUT = "logout" -COMMAND_GET_LOGIN_STATUS = "get-login-status" -COMMAND_GET_SERVER_TRANSPORT_LIST = "get-server-transport-list" -COMMAND_ADD_SERVER_PARTITION = "add-server-partition" -COMMAND_ADD_VOLUME_USER = "add-volume-user" -COMMAND_GET_PARTITION_VOLUME_LIST = "get-partition-volume-list" -COMMAND_GET_VOLUME_USER_INFO = "get-volume-user-info" -COMMAND_GET_VOLUME_USER_LIST = "get-volume-user-list" -COMMAND_MIGRATE_PARTITION_BACKGROUND = "migrate-partition-background" -COMMAND_MIGRATE_PARTITION_STATUS = "migrate-partition-status" -COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_BACKGROUND = "migrate-volume-server-partition-background" -COMMAND_MIGRATE_VOLUME_SERVER_PARTITION_STATUS = "migrate-volume-server-partition-status" -COMMAND_REMOVE_SERVER_PARTITION = "remove-server-partition" -COMMAND_REMOVE_VOLUME_USER = "remove-volume-user" -COMMAND_RENAME_VOLUME_USER = "rename-volume-user" -COMMAND_RENAME_VOLUME = "rename-volume" -COMMAND_RUN_SERVER_SERVICE = "run-server-service" -COMMAND_SET_VOLUME_USER_PASSWORD = "set-volume-user-password" -COMMAND_STOP_PARTITION_MIGRATION = "stop-partition-migration" -COMMAND_STOP_VOLUME_SERVER_PARTITION_MIGRATION = "stop-volume-server-partition-migration" -COMMAND_GET_SERVER_DISK_INFO = "get-server-disk-info" -COMMAND_INITIALIZE_SERVER_DISK = "initialize-server-disk" -COMMAND_SET_SERVER_COUNT = "set-server-count" -COMMAND_GET_SERVER_COUNT = "get-server-count" diff --git a/src/com.gluster.storage.management.server.scripts/src/Common.py b/src/com.gluster.storage.management.server.scripts/src/Common.py deleted file mode 100644 index c85e9a2b..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Common.py +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2009 Gluster, Inc. -# This file is part of GlusterSP. -# -# GlusterSP is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published -# by the Free Software Foundation; either version 3 of the License, -# or (at your option) any later version. -# -# GlusterSP 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 -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import syslog - diff --git a/src/com.gluster.storage.management.server.scripts/src/Disk.py b/src/com.gluster.storage.management.server.scripts/src/Disk.py deleted file mode 100755 index 2c47d396..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Disk.py +++ /dev/null @@ -1,140 +0,0 @@ -# Copyright (c) 2009 Gluster, Inc. -# This file is part of GlusterSP. -# -# GlusterSP is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published -# by the Free Software Foundation; either version 3 of the License, -# or (at your option) any later version. -# -# GlusterSP 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 -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import dbus - -class Disk: - def __init__(self): - """init""" - - self.volumes = [] - self.disks = [] - self.bus = dbus.SystemBus() - self.hal_obj = self.bus.get_object("org.freedesktop.Hal", - "/org/freedesktop/Hal/Manager") - self.hal = dbus.Interface(self.hal_obj, "org.freedesktop.Hal.Manager") - self.devices = [] - self.devices = self.hal.FindDeviceByCapability("storage") - - self.detect_disks() - self.detect_mountable_volumes() - - def getDiskList(self): - - return self.disks - - def getMountableDiskList(self): - - return self.volumes - - def detect_disks(self): - for device in self.devices: - dev = self._get_device(device) - if dev.GetProperty("storage.drive_type") != "cdrom": - if not dev.GetProperty("block.is_volume"): - self._add_disks(dev) - continue - - def _add_disks(self, dev): - disk = str(dev.GetProperty('block.device')) - disk_size = str(int(dev.GetProperty('storage.size')) / 1024**2) - - try: - if dev.GetProperty('storage.removable'): - disk_size = str(int(dev.GetProperty('storage.removable.media_size')) / 1024**2) - except: - return - - self.disks.append({ - 'device': disk, - 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')), - 'interface': str(dev.GetProperty('storage.bus')), - 'size': disk_size, - 'drive_type': str(dev.GetProperty('storage.drive_type')) - }) - - def detect_mountable_volumes(self): - """ Detect all mountable volumes using HAL via D-Bus """ - for device in self.devices: - dev = self._get_device(device) - if dev.GetProperty("storage.drive_type") != "cdrom": - if dev.GetProperty("block.is_volume"): - self._add_volume(dev) - continue - else: # iterate over children looking for a volume - children = self.hal.FindDeviceStringMatch("info.parent", - device) - if not children and "disk" == dev.GetProperty("storage.drive_type"): - self._add_volume(dev) - for child in children: - child = self._get_device(child) - if child.GetProperty("block.is_volume"): - self._add_volume(child, parent=dev) - #break # don't break, allow all partitions - - def _add_volume(self, dev, parent=None): - volume = str(dev.GetProperty('block.device')) - if not parent: - self.volumes.append ({ - 'device' : volume, - 'label' : str(dev.GetProperty('block.device')), - 'fstype' : None, - 'fsversion': None, - 'uuid' : None, - 'interface': str(dev.GetProperty('storage.bus')), - 'parent' : None, - 'description': str(dev.GetProperty('storage.model')) + " " + str(dev.GetProperty('storage.vendor')), - 'size' : None, - 'totalsize' : str(int(dev.GetProperty('storage.size')) / 1024**2), - 'drive_type': str(dev.GetProperty('storage.drive_type')), - 'mount_point': "NA" - }) - return - - self.volumes.append ({ - 'device' : volume, - 'label' : str(dev.GetProperty('volume.label')), - 'fstype' : str(dev.GetProperty('volume.fstype')), - 'fsversion': str(dev.GetProperty('volume.fsversion')), - 'uuid' : str(dev.GetProperty('volume.uuid')), - 'interface': str(parent.GetProperty('storage.bus')), - 'parent' : str(parent.GetProperty('block.device')), - 'description': str(parent.GetProperty('storage.model')) + " " + str(parent.GetProperty('storage.vendor')), - 'size' : str(int(dev.GetProperty('volume.size')) / 1024**2), - 'totalsize' : str(int(parent.GetProperty('storage.size')) / 1024**2), - 'drive_type': str(parent.GetProperty('storage.drive_type')), - 'mount_point': str(dev.GetProperty('volume.mount_point')) - }) - return - - def _get_device(self, udi): - """ Return a dbus Interface to a specific HAL device UDI """ - dev_obj = self.bus.get_object("org.freedesktop.Hal", udi) - return dbus.Interface(dev_obj, "org.freedesktop.Hal.Device") - - def get_free_bytes(self, device=None): - """ Return the number of available bytes on our device """ - import statvfs - stat = os.statvfs(device) - return stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] - - def get_used_bytes(self, device=None): - """ Return the number of used bytes on our device """ - import statvfs - stat = os.statvfs(device) - return ((stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS]) - (stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL])) diff --git a/src/com.gluster.storage.management.server.scripts/src/DiskUtils.py b/src/com.gluster.storage.management.server.scripts/src/DiskUtils.py deleted file mode 100644 index 4fadc71a..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/DiskUtils.py +++ /dev/null @@ -1,948 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import glob -from copy import deepcopy -import dbus -import Globals -import time -import Utils -import Disk -import Protocol -from FsTabUtils import * - -ONE_MB_SIZE = 1048576 - - -def _stripDev(device): - if Utils.isString(device) and device.startswith("/dev/"): - return device[5:] - return device - - -def _addDev(deviceName): - if Utils.isString(deviceName) and not deviceName.startswith("/dev/"): - return "/dev/" + deviceName - return deviceName - - -def getDeviceName(device): - if type(device) == type([]): - nameList = [] - for d in device: - nameList.append(_stripDev(d)) - return nameList - return _stripDev(device) - - -def getDevice(deviceName): - if Utils.isString(deviceName): - return _addDev(deviceName) - if type(deviceName) == type([]): - nameList = [] - for d in deviceName: - nameList.append(_addDev(d)) - return nameList - return _addDev(deviceName) - - -def getDiskPartitionByUuid(uuid): - uuidFile = "/dev/disk/by-uuid/%s" % uuid - if os.path.exists(uuidFile): - return getDeviceName(os.path.realpath(uuidFile)) - return None - - -def getUuidByDiskPartition(device): - for uuidFile in glob.glob("/dev/disk/by-uuid/*"): - if os.path.realpath(uuidFile) == device: - return os.path.basename(uuidFile) - return None - - -def getDiskPartitionUuid(partition): - Utils.log("WARNING: getDiskPartitionUuid() is deprecated by getUuidByDiskPartition()") - return getUuidByDiskPartition(partition) - - -def getDiskPartitionByLabel(label): - ## TODO: Finding needs to be enhanced - labelFile = "/dev/disk/by-label/%s" % label - if os.path.exists(labelFile): - if os.path.islink(labelFile): - return getDeviceName(os.path.realpath(labelFile)) - return None - - -def getDeviceByLabel(label): - Utils.log("WARNING: getDeviceByLabel() is deprecated by getDiskPartitionByLabel()") - return getDiskPartitionByLabel(label) - - -def getDiskPartitionLabel(device): - rv = Utils.runCommandFG(["sudo", "e2label", device], stdout=True) - if rv["Status"] == 0: - return rv["Stdout"].strip() - return False - - -def readFile(fileName): - lines = None - try: - fp = open(fileName) - lines = fp.readlines() - fp.close() - except IOError, e: - Utils.log("failed to read file %s: %s" % (file, str(e))) - return lines - - -def getRootPartition(fsTabFile=Globals.FSTAB_FILE): - fsTabEntryList = readFsTab(fsTabFile) - for fsTabEntry in fsTabEntryList: - if fsTabEntry["MountPoint"] == "/": - if fsTabEntry["Device"].startswith("UUID="): - return getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1]) - if fsTabEntry["Device"].startswith("LABEL="): - partitionName = getDiskPartitionByLabel(fsTabEntry["Device"].split("LABEL=")[-1]) - if partitionName: - return partitionName - return getDeviceName(fsTabEntry["Device"]) - return None - -def getMounts(): - mounts = {} - for line in readFile("/proc/mounts"): - str = line.strip() - if str.startswith("/dev/"): - tokens = str.split() - device = {} - mountPoint = tokens[1].strip() - device["MountPoint"] = mountPoint - device["FsType"] = tokens[2].strip() - device["Uuid"] = getDiskPartitionUuid(tokens[0].strip()) - device["Status"] = "INITIALIZED" - if mountPoint: - if "/export/" in mountPoint: - device["Type"] = "DATA" - else: - device["Type"] = "BOOT" - else: - device["Type"] = "UNKNOWN" - mounts[tokens[0].strip()] = device - return mounts - -def getRaidDisk(): - array = [] - arrayList = [] - mdFound = False - - try: - fp = open("/proc/mdstat") - for line in fp: - str = line.strip() - if str.startswith("md"): - array.append(str) - mdFound = True - continue - if mdFound: - if str: - array.append(str) - else: - arrayList.append(array) - array = [] - mdFound = False - fp.close() - except IOError, e: - return None - - raidList = {} - for array in arrayList: - raid = {} - tokens = array[0].split() - raid['Interface'] = tokens[3] - device = getDevice(tokens[0]) - raid['MountPoint'] = getDeviceMountPoint(device) - if raid['MountPoint']: - if "/export/" in raid['MountPoint']: - raid['Type'] = "DATA" - else: - raid['Type'] = "BOOT" - else: - raid['Type'] = "UNKNOWN" - rv = Utils.runCommand("blkid -c /dev/null %s" % (device), output=True, root=True) - raid['Uuid'] = None - raid['FsType'] = None - raid['Status'] = "UNINITIALIZED" - if isDiskInFormatting(device): - raid['Status'] = "INITIALIZING" - if not rv["Stderr"]: - words = rv["Stdout"].strip().split() - if words: - raid['Status'] = "INITIALIZED" - if len(words) > 2: - raid['Uuid'] = words[1].split("UUID=")[-1].split('"')[1] - raid['FsType'] = words[2].split("TYPE=")[-1].split('"')[1] - - used = 0 - rv = Utils.runCommand("df %s" % (device), output=True, root=True) - if rv["Status"] == 0: - try: - used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024 - except IndexError: - pass - except ValueError: - pass - raid['SpaceInUse'] = used - raid['Disks'] = [x.split('[')[0] for x in tokens[4:]] - raid['Size'] = float(array[1].split()[0]) / 1024.0 - raidList[tokens[0]] = raid - return raidList - - -def getOsDisk(): - Utils.log("WARNING: getOsDisk() is deprecated by getRootPartition()") - return getRootPartition() - - -def getDiskInfo(diskDeviceList=None): - diskDeviceList = getDevice(diskDeviceList) - if Utils.isString(diskDeviceList): - diskDeviceList = [diskDeviceList] - - mounts = getMounts() - if Utils.runCommand("/usr/bin/lshal") != 0: - Utils.log("failed running /usr/bin/lshal") - - dbusSystemBus = dbus.SystemBus() - halObj = dbusSystemBus.get_object("org.freedesktop.Hal", - "/org/freedesktop/Hal/Manager") - halManager = dbus.Interface(halObj, "org.freedesktop.Hal.Manager") - storageUdiList = halManager.FindDeviceByCapability("storage") - - diskInfo = {} - diskList = [] - for udi in storageUdiList: - halDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal", udi) - halDevice = dbus.Interface(halDeviceObj, - "org.freedesktop.Hal.Device") - if halDevice.GetProperty("storage.drive_type") in ["cdrom", "floppy"] or \ - halDevice.GetProperty("block.is_volume"): - continue - disk = {} - disk["Device"] = str(halDevice.GetProperty('block.device')) - if diskDeviceList and disk["Device"] not in diskDeviceList: - continue - disk["Description"] = str(halDevice.GetProperty('storage.vendor')) + " " + str(halDevice.GetProperty('storage.model')) - if halDevice.GetProperty('storage.removable'): - disk["Size"] = long(halDevice.GetProperty('storage.removable.media_size')) - else: - disk["Size"] = long(halDevice.GetProperty('storage.size')) / 1024**2 - disk["Interface"] = str(halDevice.GetProperty('storage.bus')) - disk["DriveType"] = str(halDevice.GetProperty('storage.drive_type')) - disk["Status"] = None - disk["Uuid"] = None - disk["Init"] = False - disk["Type"] = None - disk["FsType"] = None - disk["FsVersion"] = None - disk["MountPoint"] = None - disk["ReadOnlyAccess"] = None - disk["SpaceInUse"] = None - - partitionUdiList = halManager.FindDeviceStringMatch("info.parent", udi) - if isDiskInFormatting(disk["Device"]): - disk["Status"] = "INITIALIZING" - else: - if partitionUdiList: - disk["Status"] = "INITIALIZED" - else: - disk["Status"] = "UNINITIALIZED" - disk["Type"] = "UNKNOWN" - - if mounts and mounts.has_key(disk["Device"]): - disk["Uuid"] = mounts[disk["Device"]]["Uuid"] - disk["Type"] = mounts[disk["Device"]]["Type"] - disk["Status"] = mounts[disk["Device"]]["Status"] - disk["FsType"] = mounts[disk["Device"]]["FsType"] - disk["MountPoint"] = mounts[disk["Device"]]["MountPoint"] - - partitionList = [] - diskSpaceInUse = 0 - for partitionUdi in partitionUdiList: - used = 0 - partitionHalDeviceObj = dbusSystemBus.get_object("org.freedesktop.Hal", - partitionUdi) - partitionHalDevice = dbus.Interface(partitionHalDeviceObj, - "org.freedesktop.Hal.Device") - if not partitionHalDevice.GetProperty("block.is_volume"): - continue - partitionDevice = str(partitionHalDevice.GetProperty('block.device')) - if partitionHalDevice.GetProperty("volume.is_mounted"): - rv = Utils.runCommandFG(["df", str(partitionHalDevice.GetProperty('volume.mount_point'))], stdout=True) - if rv["Status"] == 0: - try: - used = long(rv["Stdout"].split("\n")[1].split()[2]) / 1024 - diskSpaceInUse += used - except IndexError: - pass - except ValueError: - pass - - if disk["Device"] == partitionDevice: - disk["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid')) - disk["Init"] = True # TODO: use isDataDiskPartitionFormatted function to cross verify this - disk["Status"] = "INITIALIZED" - mountPoint = str(partitionHalDevice.GetProperty('volume.mount_point')) - if mountPoint: - if "/export/" in mountPoint: - disk["Type"] = "DATA" - else: - disk["Type"] = "BOOT" - else: - disk["Type"] = "UNKNOWN" - disk["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype')) - if disk["FsType"] and "UNINITIALIZED" == disk["Status"]: - disk["Status"] = "INITIALIZED" - disk["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion')) - disk["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point')) - disk["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only')) - if not disk["Size"]: - disk["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 - disk["SpaceInUse"] = used - continue - - partition = {} - partition["Init"] = False - partition["Type"] = "UNKNOWN" - partition["Device"] = partitionDevice - partition["Uuid"] = str(partitionHalDevice.GetProperty('volume.uuid')) - partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 - partition["FsType"] = str(partitionHalDevice.GetProperty('volume.fstype')) - partition["FsVersion"] = str(partitionHalDevice.GetProperty('volume.fsversion')) - partition["Label"] = str(partitionHalDevice.GetProperty('volume.label')) - partition["MountPoint"] = str(partitionHalDevice.GetProperty('volume.mount_point')) - partition["Size"] = long(partitionHalDevice.GetProperty('volume.size')) / 1024**2 - - if isDiskInFormatting(partitionDevice): - partition["Status"] = "INITIALIZING" - else: - if partition["FsType"]: - partition["Status"] = "INITIALIZED" - else: - partition["Status"] = "UNINITIALIZED" - - partition["SpaceInUse"] = used - if partition["MountPoint"] or isDataDiskPartitionFormatted(partitionDevice): - partition["Init"] = True - partition["Status"] = "INITIALIZED" - if partition["MountPoint"]: - if "/export/" in partition["MountPoint"]: - partition["Type"] = "DATA" - else: - partition["Type"] = "BOOT" - else: - if "SWAP" == partition["FsType"].strip().upper(): - partition["Type"] = "SWAP" - partition["ReadOnlyAccess"] = str(partitionHalDevice.GetProperty('volume.is_mounted_read_only')) - partitionList.append(partition) - disk["Partitions"] = partitionList - if not disk["SpaceInUse"]: - disk["SpaceInUse"] = diskSpaceInUse - diskList.append(disk) - diskInfo["disks"] = diskList - if diskList: - return diskInfo - for line in readFile("/proc/partitions")[2:]: - disk = {} - tokens = line.split() - if tokens[3].startswith("md"): - continue - disk["Device"] = tokens[3] - ## if diskDeviceList and disk["Device"] not in diskDeviceList: - ## continue - disk["Description"] = None - disk["Size"] = long(tokens[2]) / 1024 - disk["Status"] = None - disk["Interface"] = None - disk["DriveType"] = None - disk["Uuid"] = None - disk["Init"] = False - disk["Type"] = None - disk["FsType"] = None - disk["FsVersion"] = None - disk["MountPoint"] = None - disk["ReadOnlyAccess"] = None - disk["SpaceInUse"] = None - disk["Partitions"] = [] - diskList.append(disk) - diskInfo["disks"] = diskList - return diskInfo - -def getDiskList(diskDeviceList=None): - return diskInfo["disks"] - -def readFsTab(fsTabFile=Globals.FSTAB_FILE): - try: - fsTabfp = open(fsTabFile) - except IOError, e: - Utils.log("readFsTab(): " + str(e)) - return None - - fsTabEntryList = [] - for line in fsTabfp: - tokens = line.strip().split() - if not tokens or tokens[0].startswith('#'): - continue - fsTabEntry = {} - fsTabEntry["Device"] = None - fsTabEntry["MountPoint"] = None - fsTabEntry["FsType"] = None - fsTabEntry["Options"] = None - fsTabEntry["DumpOption"] = 0 - fsTabEntry["fsckOrder"] = 0 - try: - fsTabEntry["Device"] = tokens[0] - fsTabEntry["MountPoint"] = tokens[1] - fsTabEntry["FsType"] = tokens[2] - fsTabEntry["Options"] = tokens[3] - fsTabEntry["DumpOption"] = tokens[4] - fsTabEntry["fsckOrder"] = tokens[5] - except IndexError: - pass - if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]: - fsTabEntryList.append(fsTabEntry) - fsTabfp.close() - return fsTabEntryList - - -def checkDiskMountPoint(diskMountPoint): - try: - fstabEntries = open(Globals.FSTAB_FILE).readlines() - except IOError: - fstabEntries = [] - found = False - for entry in fstabEntries: - entry = entry.strip() - if not entry: - continue - entries = entry.split() - if entries and len(entries) > 1 and entries[0].startswith("UUID=") and entries[1].upper() == diskMountPoint.upper(): - return True - return False - - -def getMountPointByUuid(partitionUuid): - # check uuid in etc/fstab - try: - fstabEntries = open(Globals.FSTAB_FILE).readlines() - except IOError: - fstabEntries = [] - found = False - for entry in fstabEntries: - entry = entry.strip() - if not entry: - continue - if entry.split()[0] == "UUID=" + partitionUuid: - return entry.split()[1] - return None - - -def getDiskSizeInfo(partition): - # get values from df output - total = None - used = None - free = None - command = "df -kl -t ext3 -t ext4 -t xfs" - rv = Utils.runCommandFG(command, stdout=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"])) - return None, None, None - for line in rv["Stdout"].split("\n"): - tokens = line.split() - if len(tokens) < 4: - continue - if tokens[0] == partition: - total = int(tokens[1]) / 1024.0 - used = int(tokens[2]) / 1024.0 - free = int(tokens[3]) / 1024.0 - break - - if total: - return total, used, free - - # get total size from parted output - for i in range(len(partition), 0, -1): - pos = i - 1 - if not partition[pos].isdigit(): - break - disk = partition[:pos+1] - partitionNumber = partition[pos+1:] - if not partitionNumber.isdigit(): - return None, None, None - - number = int(partitionNumber) - command = "parted -ms %s unit kb print" % disk - rv = Utils.runCommandFG(command, stdout=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - Utils.log("failed to get disk details. %s" % Utils.stripEmptyLines(rv["Stdout"])) - return None, None, None - - lines = rv["Stdout"].split(";\n") - if len(lines) < 3: - return None,None,None - - for line in lines[2:]: - tokens = line.split(':') - if len(tokens) < 4: - continue - if tokens[0] == str(number): - total = int(tokens[3].split('kB')[0]) / 1024.0 - break - return total, used, free - - -def isDataDiskPartitionFormatted(device): - #Todo: Proper label needs to be added for data partition - #if getDiskPartitionLabel(device) != Globals.DATA_PARTITION_LABEL: - # return False - device = getDeviceName(device) - diskObj = Disk.Disk() - for disk in diskObj.getMountableDiskList(): - if disk['device'].upper() == device.upper(): - mountPoint = disk['mount_point'] - if not mountPoint: - return False - if not os.path.exists(mountPoint): - return False - - uuid = getUuidByDiskPartition(device) - if not uuid: - return False - - for fsTabEntry in readFsTab(): - if fsTabEntry["Device"] == ("UUID=%s" % uuid) and fsTabEntry["MountPoint"] == mountPoint: - return True - return False - - -def getDiskDom(diskDeviceList=None, bootPartition=None, skipDisk=None): - diskDeviceList = getDevice(diskDeviceList) - if Utils.isString(diskDeviceList): - diskDeviceList = [diskDeviceList] - - if skipDisk: - skipDisk = getDevice(skipDisk) - if Utils.isString(skipDisk): - skipDisk = [skipDisk] - - diskInfo = getDiskInfo(diskDeviceList) - diskList = diskInfo["disks"] - if not diskList: - return None - - raidPartitions = {} - raidDisk = getRaidDisk() - - for k, v in raidDisk.iteritems(): - for i in v['Disks']: - raidPartitions[i] = k - - #for partition in raidDisk.values(): - # raidDiskPartitions += partition['disks'] - - diskDom = Protocol.XDOM() - disksTag = diskDom.createTag("disks", None) - raidDisks = {} - if not bootPartition: - bootPartition = getRootPartition() - for disk in diskList: - if skipDisk and disk["Device"] in skipDisk: - continue - diskTag = diskDom.createTag("disk", None) - diskDevice = getDeviceName(disk["Device"]) - diskTag.appendChild(diskDom.createTag("name", diskDevice)) - diskTag.appendChild(diskDom.createTag("description", disk["Description"])) - diskTag.appendChild(diskDom.createTag("uuid", disk["Uuid"])) - diskTag.appendChild(diskDom.createTag("status", disk["Status"])) - diskTag.appendChild(diskDom.createTag("interface", disk["Interface"])) - - #if not disk["Partitions"]: - diskTag.appendChild(diskDom.createTag("type", disk["Type"])) - #diskTag.appendChild(diskDom.createTag("init", str(disk["Init"]).lower())) - diskTag.appendChild(diskDom.createTag("fsType", disk["FsType"])) - diskTag.appendChild(diskDom.createTag("fsVersion", disk["FsVersion"])) - diskTag.appendChild(diskDom.createTag("mountPoint", disk["MountPoint"])) - - diskTag.appendChild(diskDom.createTag("size", disk["Size"])) - diskTag.appendChild(diskDom.createTag("spaceInUse", disk["SpaceInUse"])) - partitionsTag = diskDom.createTag("partitions", None) - if raidPartitions.has_key(diskDevice): - rdList = {} - rdList[diskDevice] = [deepcopy(diskTag)] - if not raidDisks.has_key(raidPartitions[diskDevice]): - raidDisks[raidPartitions[diskDevice]] = [] - raidDisks[raidPartitions[diskDevice]] += [rdList] - continue - for partition in disk["Partitions"]: - partitionTag = diskDom.createTag("partition", None) - device = getDeviceName(partition["Device"]) - partitionTag.appendChild(diskDom.createTag("name", device)) - if partition["Uuid"]: #TODO: Move this verification and findings to getDiskInfo function - partitionTag.appendChild(diskDom.createTag("uuid", partition["Uuid"])) - else: - partitionTag.appendChild(diskDom.createTag("uuid", getUuidByDiskPartition("/dev/" + device))) - partitionTag.appendChild(diskDom.createTag("status", partition["Status"])) - #partitionTag.appendChild(diskDom.createTag("init", str(partition["Init"]).lower())) - partitionTag.appendChild(diskDom.createTag("type", str(partition["Type"]))) - partitionTag.appendChild(diskDom.createTag("fsType", partition["FsType"])) - partitionTag.appendChild(diskDom.createTag("mountPoint", partition['MountPoint'])) - partitionTag.appendChild(diskDom.createTag("size", partition["Size"])) - partitionTag.appendChild(diskDom.createTag("spaceInUse", partition["SpaceInUse"])) - if raidPartitions.has_key(device): - tempPartitionTag = diskDom.createTag("partitions", None) - if raidDisks.has_key(raidPartitions[device]): - rdList = raidDisks[raidPartitions[device]] - for rdItem in rdList: - if not rdItem.has_key(diskDevice): - rdItem[diskDevice] = [deepcopy(diskTag), tempPartitionTag] - rdItem[diskDevice][0].appendChild(tempPartitionTag) - rdItem[diskDevice][-1].appendChild(partitionTag) - continue - rdList = {} - rdList[diskDevice] = [deepcopy(diskTag), tempPartitionTag] - tempPartitionTag.appendChild(partitionTag) - rdList[diskDevice][0].appendChild(tempPartitionTag) - raidDisks[raidPartitions[device]] = [rdList] - continue - partitionsTag.appendChild(partitionTag) - diskTag.appendChild(partitionsTag) - disksTag.appendChild(diskTag) - - for rdisk in raidDisk.keys(): - raidDiskTag = diskDom.createTag("disk", None) - raidDiskTag.appendChild(diskDom.createTag("name", rdisk)) - raidDiskTag.appendChild(diskDom.createTag("description")) - raidDiskTag.appendChild(diskDom.createTag("uuid", raidDisk[rdisk]['Uuid'])) - raidDiskTag.appendChild(diskDom.createTag("type", raidDisk[rdisk]['Type'])) - raidDiskTag.appendChild(diskDom.createTag("mountPoint", raidDisk[rdisk]['MountPoint'])) - raidDiskTag.appendChild(diskDom.createTag("status", raidDisk[rdisk]['Status'])) - raidDiskTag.appendChild(diskDom.createTag("interface", raidDisk[rdisk]['Interface'])) - raidDiskTag.appendChild(diskDom.createTag("fsType", raidDisk[rdisk]['FsType'])) - raidDiskTag.appendChild(diskDom.createTag("fsVersion")) - raidDiskTag.appendChild(diskDom.createTag("size", raidDisk[rdisk]['Size'])) - raidDiskTag.appendChild(diskDom.createTag("spaceInUse", raidDisk[rdisk]['SpaceInUse'])) - raidDisksTag = diskDom.createTag("raidDisks", None) - if raidDisks.has_key(rdisk): - for item in raidDisks[rdisk]: - for diskTag in item.values(): - raidDisksTag.appendChild(diskTag[0]) - raidDiskTag.appendChild(raidDisksTag) - disksTag.appendChild(raidDiskTag) - diskDom.addTag(disksTag) - return diskDom - - -def initializeDisk(disk, boot=False, startSize=0, sudo=False): - if boot and startSize > 0: - return False - - disk = getDevice(disk) - diskObj = getDiskList(disk)[0] - - if boot or startSize == 0: - command = "dd if=/dev/zero of=%s bs=1024K count=1" % diskObj["Device"] - if runCommandFG(command, root=sudo) != 0: - if boot: - Utils.log("failed to clear boot sector of disk %s" % diskObj["Device"]) - return False - Utils.log("failed to clear boot sector of disk %s. ignoring" % diskObj["Device"]) - - command = "parted -s %s mklabel gpt" % diskObj["Device"] - if runCommandFG(command, root=sudo) != 0: - return False - - if boot: - command = "parted -s %s mkpart primary ext3 0MB %sMB" % (diskObj["Device"], Globals.OS_PARTITION_SIZE) - if runCommandFG(command, root=sudo) != 0: - return False - command = "parted -s %s set 1 boot on" % (diskObj["Device"]) - if runCommandFG(command, root=sudo) != 0: - return False - startSize = Globals.OS_PARTITION_SIZE - - size = (diskObj["Size"] / ONE_MB_SIZE) - startSize - while size > Globals.MAX_PARTITION_SIZE: - endSize = startSize + Globals.MAX_PARTITION_SIZE - command = "parted -s %s mkpart primary ext3 %sMB %sMB" % (diskObj["Device"], startSize, endSize) - if runCommandFG(command, root=sudo) != 0: - return False - size -= Globals.MAX_PARTITION_SIZE - startSize = endSize - - if size: - command = "parted -s %s mkpart primary ext3 %sMB 100%%" % (diskObj["Device"], startSize) - if runCommandFG(command, root=sudo) != 0: - return False - - if runCommandFG("udevadm settle", root=sudo) != 0: - if runCommandFG("udevadm settle", root=sudo) != 0: - Utils.log("udevadm settle for disk %s failed. ignoring" % diskObj["Device"]) - time.sleep(1) - - if runCommandFG("partprobe %s" % diskObj["Device"], root=sudo) != 0: - Utils.log("partprobe %s failed" % diskObj["Device"]) - return False - - if runCommandFG("gptsync %s" % diskObj["Device"], root=sudo) != 0: - Utils.log("gptsync %s failed. ignoring" % diskObj["Device"]) - - # wait forcefully to appear devices in /dev - time.sleep(2) - return True - - -def initializeOsDisk(diskObj): - Utils.log("WARNING: initializeOsDisk() is deprecated by initializeDisk(boot=True)") - return initializeDisk(diskObj, boot=True) - - -def initializeDataDisk(diskObj): - Utils.log("WARNING: initializeDataDisk() is deprecated by initializeDisk()") - return initializeDisk(diskObj) - -def getBootPartition(serverName): - diskDom = XDOM() - diskDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - if not diskDom: - return None - partitionDom = XDOM() - partitionUuid = None - partitionName = None - for partitionTag in diskDom.getElementsByTagRoute("disk.partition"): - partitionDom.setDomObj(partitionTag) - boot = partitionDom.getTextByTagRoute("boot") - if boot and boot.strip().upper() == 'YES': - partitionUuid = partitionDom.getTextByTagRoute("uuid") - partitionName = partitionDom.getTextByTagRoute("device") - break - if not (partitionUuid and partitionName): - return None - - # check device label name - deviceBaseName = os.path.basename(partitionName) - process = runCommandBG(['sudo', 'e2label', partitionName]) - if type(process) == type(True): - return None - if process.wait() != 0: - return None - output = process.communicate() - deviceLabel = output[0].split()[0] - if deviceLabel != Globals.BOOT_PARTITION_LABEL: - return None - - # check uuid in etc/fstab - try: - fstabEntries = open(Globals.FSTAB_FILE).readlines() - except IOError: - fstabEntries = [] - found = False - for entry in fstabEntries: - entry = entry.strip() - if not entry: - continue - if entry.split()[0] == "UUID=" + partitionUuid: - found = True - break - if not found: - return None - return partitionName - - -def isDiskInFormatting(device): - DEVICE_FORMAT_LOCK_FILE = "/var/lock/%s.lock" % device - return os.path.exists(DEVICE_FORMAT_LOCK_FILE) - - -def isDiskInFormat(device): - Utils.log("WARNING: isDiskInFormat() is deprecated by isDataDiskPartitionFormatted()") - return isDataDiskPartitionFormatted(device) - - -def diskOrder(serverExportList): - newServerExportList = [] - while serverExportList: - serverExport = deepcopy(serverExportList[0]) - if newServerExportList and serverExport.split(":")[0] == newServerExportList[-1].split(":")[0]: - inserted = False - for i in range(0, len(newServerExportList) - 1): - if serverExport.split(":")[0] == newServerExportList[i].split(":")[0]: - continue - if i == 0: - newServerExportList.insert(i, serverExport) - inserted = True - break - if serverExport.split(":")[0] == newServerExportList[i - 1].split(":")[0]: - continue - newServerExportList.insert(i, serverExport) - inserted = True - break - if not inserted: - newServerExportList.append(serverExport) - else: - newServerExportList.append(serverExport) - serverExportList.remove(serverExport) - i = 0 - while serverExportList and i < len(serverExportList): - if serverExport.split(":")[0] == serverExportList[i].split(":")[0]: - i += 1 - continue - serverExport = deepcopy(serverExportList[i]) - newServerExportList.append(serverExport) - serverExportList.remove(serverExport) - return newServerExportList - - -def updateServerDiskConfig(serverName, diskDom, requestFlag=True, partitionFlag=True): - command = "command.server." - if not requestFlag: - command = "" - diskList = {} - for tagE in diskDom.getElementsByTagRoute(command + "disk"): - diskList[diskDom.getTextByTagRoute(command + "device")] = tagE - configDom = XDOM() - if not configDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): - return diskDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - diskTag = configDom.getElementsByTagRoute("disks.disk") - disks = configDom.getElementsByTagRoute("disks") - if not (diskTag or disks): - return None - for tagE in diskTag: - diskDom = XDOM() - diskDom.setDomObj(tagE) - device = diskDom.getTextByTagRoute("device") - if partitionFlag and device in diskList: - disks[0].removeChild(tagE) - disks[0].appendChild(deepcopy(diskList[device])) - continue - if not partitionFlag and device in diskList: - partitionList = [] - for childNodeTag in tagE.childNodes: - if childNodeTag.nodeName == 'partition': - partitionList.append(childNodeTag) - tagE.childNodes = [] - tagE.childNodes = diskList[device].childNodes + partitionList - return configDom.writexml("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - - -def compareDisksDom(diskDomA, diskDomB, requestFlag=True): - command = "command.server.disk." - if not requestFlag: - command = "" - sourceDiskList = {} - sourceDisk = {} - for tagE in diskDomA.getElementsByTagRoute("disk"): - sourceDisk["description"] = diskDomA.getTextByTagRoute("description") - sourceDisk["size"] = diskDomA.getTextByTagRoute("size") - sourceDisk["init"] = diskDomA.getTextByTagRoute("init") - sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface") - sourceDiskList[diskDomA.getTextByTagRoute("device")] = sourceDisk - objDiskList = {} - objDisk = {} - for tagE in diskDomB.getElementsByTagRoute("disk"): - objDisk["description"] = diskDomB.getTextByTagRoute("description") - objDisk["size"] = diskDomB.getTextByTagRoute("size") - objDisk["init"] = diskDomB.getTextByTagRoute("init") - objDisk["interface"] = diskDomB.getTextByTagRoute("interface") - objDiskList[diskDomB.getTextByTagRoute("device")] = objDisk - return sourceDiskList == objDiskList - - -def compareDiskDom(diskDomA, diskDomB, requestFlag=True): - command = "command.server.disk." - if not requestFlag: - command = "" - sourceDisk = {} - sourceDisk["device"] = diskDomA.getTextByTagRoute("device") - sourceDisk["description"] = diskDomA.getTextByTagRoute("description") - sourceDisk["size"] = diskDomA.getTextByTagRoute("size") - sourceDisk["init"] = diskDomA.getTextByTagRoute("init") - sourceDisk["interface"] = diskDomA.getTextByTagRoute("interface") - for tagE in diskDomA.getElementsByTagRoute("partition"): - sourceDiskPartitions = {} - partitionDom = XDOM() - partitionDom.setDomObj(tagE) - sourceDiskPartitions["size"] = partitionDom.getTextByTagRoute("size") - #sourceDiskPartitions["free"] = partitionDom.getTextByTagRoute("free") - sourceDiskPartitions["format"] = partitionDom.getTextByTagRoute("format") - sourceDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid") - sourceDisk[partitionDom.getTextByTagRoute("device")] = sourceDiskPartitions - - objDisk = {} - objDisk["device"] = diskDomB.getTextByTagRoute(command + "device") - objDisk["description"] = diskDomB.getTextByTagRoute(command + "description") - objDisk["size"] = diskDomB.getTextByTagRoute(command + "size") - objDisk["init"] = diskDomB.getTextByTagRoute(command + "init") - objDisk["interface"] = diskDomB.getTextByTagRoute(command + "interface") - for tagE in diskDomB.getElementsByTagRoute(command + "partition"): - objDiskPartitions = {} - partitionDom = XDOM() - partitionDom.setDomObj(tagE) - objDiskPartitions["size"] = partitionDom.getTextByTagRoute("size") - #objDiskPartitions["free"] = partitionDom.getTextByTagRoute("free") - objDiskPartitions["format"] = partitionDom.getTextByTagRoute("format") - objDiskPartitions["uuid"] = partitionDom.getTextByTagRoute("uuid") - objDisk[partitionDom.getTextByTagRoute("device")] = objDiskPartitions - return sourceDisk == objDisk - - -def getServerConfigDiskDom(serverName, diskName=None): - diskConfigDom = XDOM() - if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): - Utils.log("Unable to parse %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - return None - diskTag = diskConfigDom.getElementsByTagRoute("disks.disk") - if not diskTag: - Utils.log("Unable to reterive disk information %s/%s/disk.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - return None - if diskName: - for tagE in diskTag: - diskDom = XDOM() - diskDom.setDomObj(tagE) - if diskName == diskDom.getTextByTagRoute("device"): - return diskDom - return None - - for tagE in diskTag: - for partitionTag in tagE.getElementsByTagName("partition"): - tagE.removeChild(partitionTag) - return diskConfigDom - - -def getDeviceMountPoint(device): - try: - fp = open("/proc/mounts") - for token in [line.strip().split() for line in fp.readlines()]: - if token and len(token) > 2 and token[0] == device: - return token[1] - fp.close() - except IOError, e: - return None - diff --git a/src/com.gluster.storage.management.server.scripts/src/FsTabUtils.py b/src/com.gluster.storage.management.server.scripts/src/FsTabUtils.py deleted file mode 100644 index fcac4196..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/FsTabUtils.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import Globals - -def readFsTab(fsTabFile=Globals.FSTAB_FILE): - try: - fsTabfp = open(fsTabFile) - except IOError, e: - log("readFsTab(): " + str(e)) - return None - - fsTabEntryList = [] - for line in fsTabfp: - tokens = line.strip().split() - if not tokens or tokens[0].startswith('#'): - continue - fsTabEntry = {} - fsTabEntry["Device"] = None - fsTabEntry["MountPoint"] = None - fsTabEntry["FsType"] = None - fsTabEntry["Options"] = None - fsTabEntry["DumpOption"] = 0 - fsTabEntry["fsckOrder"] = 0 - try: - fsTabEntry["Device"] = tokens[0] - fsTabEntry["MountPoint"] = tokens[1] - fsTabEntry["FsType"] = tokens[2] - fsTabEntry["Options"] = tokens[3] - fsTabEntry["DumpOption"] = tokens[4] - fsTabEntry["fsckOrder"] = tokens[5] - except IndexError: - pass - if fsTabEntry["Device"] and fsTabEntry["MountPoint"] and fsTabEntry["FsType"] and fsTabEntry["Options"]: - fsTabEntryList.append(fsTabEntry) - - fsTabfp.close() - return fsTabEntryList - -def writeFsTab(fsTabEntryList, fsTabFile=Globals.FSTAB_FILE): - try: - fsTabfp = open(fsTabFile, "w") - for fsTabEntry in fsTabEntryList: - fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" % - (fsTabEntry["Device"], fsTabEntry["MountPoint"], - fsTabEntry["FsType"], fsTabEntry["Options"], - fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"])) - fsTabfp.close() - except IOError, e: - log("writeFsTab(): " + str(e)) - return False - return True - -def addFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE): - try: - fsTabfp = open(fsTabFile, "a") - fsTabfp.write("%s\t%s\t%s\t%s\t%s\t%s\n" % - (fsTabEntry["Device"], fsTabEntry["MountPoint"], - fsTabEntry["FsType"], fsTabEntry["Options"], - fsTabEntry["DumpOption"], fsTabEntry["fsckOrder"])) - fsTabfp.close() - except IOError, e: - log("addFsTabEntry(): " + str(e)) - return False - return True - -def removeFsTabEntry(fsTabEntry, fsTabFile=Globals.FSTAB_FILE): - fsTabEntryList = readFsTab(fsTabFile) - if not fsTabEntryList: - return False - - try: - fsTabEntryList.remove(fsTabEntry) - except ValueError: - return False - - return writeFsTab(fsTabEntryList, fsTabFile) - diff --git a/src/com.gluster.storage.management.server.scripts/src/GetServerNetworkConfig.py b/src/com.gluster.storage.management.server.scripts/src/GetServerNetworkConfig.py deleted file mode 100644 index 3311eb56..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/GetServerNetworkConfig.py +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import syslog -import Globals -import Commands -import re -from ServerUtils import * -from Protocol import * -from NetworkUtils import * - -def getServerNetworkConfig(requestXml): - serverName = requestXml.getTextByTagRoute("command.server-name") - version = requestXml.getVersion() - messageId = requestXml.getAttribute("id") - - if not serverName: - responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "No server name given", messageId, version) - responseDom.appendTagRoute("server.name", serverName) - return responseDom - responseDom = ResponseXml(Commands.COMMAND_GET_SERVER_NETWORK_CONFIG, "OK", messageId, version) - serverTag = responseDom.createTag("server", None) - serverTag.appendChild(responseDom.createTag("name", serverName)) - nameServerList, domain, searchDomain = readResolvConfFile() - if domain: - domainName = domain[0] - else: - domainName = None - serverTag.appendChild(responseDom.createTag("domainname", domainName)) - i = 1 - for dns in nameServerList: - serverTag.appendChild(responseDom.createTag("dns%s" % i, dns)) - i += 1 - #TODO: probe and retrieve timezone, ntp-server, preferred-network details and update the tags - configDom = XDOM() - if configDom.parseFile("%s/%s/network.xml" % (Globals.SERVER_CONF_DIR, serverName)): - serverTag.appendChild(responseDom.createTag("timezone", configDom.getTextByTagRoute("network.timezone"))) - serverTag.appendChild(responseDom.createTag("ntp-server", configDom.getTextByTagRoute("network.ntp-server"))) - preferredNetwork = configDom.getTextByTagRoute("network.preferred-network") - if not preferredNetwork: - preferredNetwork = "any" - serverTag.appendChild(responseDom.createTag("preferred-network", preferredNetwork)) - - deviceList = {} - for device in getNetDeviceList(): - deviceList[device["device"]] = device - try: - macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() - except IOError: - continue - interfaceTag = responseDom.createTag("interface", None) - interfaceTag.appendChild(responseDom.createTag("device", device["device"])) - interfaceTag.appendChild(responseDom.createTag("description", device["description"])) - interfaceTag.appendChild(responseDom.createTag("hwaddr", macAddress)) - if deviceList[device["device"]]: - if deviceList[device["device"]]["onboot"]: - interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) - else: - interfaceTag.appendChild(responseDom.createTag("onboot", "no")) - interfaceTag.appendChild(responseDom.createTag("bootproto", deviceList[device["device"]]["bootproto"])) - interfaceTag.appendChild(responseDom.createTag("ipaddr", deviceList[device["device"]]["ipaddr"])) - interfaceTag.appendChild(responseDom.createTag("netmask", deviceList[device["device"]]["netmask"])) - interfaceTag.appendChild(responseDom.createTag("gateway", deviceList[device["device"]]["gateway"])) - if deviceList[device["device"]]["mode"]: - interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) - if deviceList[device["device"]]["master"]: - interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) - spliter = re.compile(r'[\D]') - interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) - else: - interfaceTag.appendChild(responseDom.createTag("onboot", "no")) - interfaceTag.appendChild(responseDom.createTag("bootproto", "none")) - serverTag.appendChild(interfaceTag) - responseDom.appendTag(serverTag) - return responseDom - -def test(): - requestString = """ -s1""" - requestDom = RequestXml(requestString) - print getServerNetworkConfig(requestDom).toxml() diff --git a/src/com.gluster.storage.management.server.scripts/src/Globals.py b/src/com.gluster.storage.management.server.scripts/src/Globals.py deleted file mode 100644 index f8a07c25..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Globals.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -MULTICAST_GROUP = '224.224.1.1' -MULTICAST_PORT = 5353 -GLUSTER_PLATFORM_VERSION = "3.2" - -## System configuration constants -SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" -DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" - -FSTAB_FILE = "/etc/fstab" -NFS_EXPORTS_FILE = "/etc/exports" -SAMBA_CONF_FILE = "/etc/samba/smb.conf" -TIMEZONE_FILE = "/etc/timezone" -ZONEINFO_DIR = "/usr/share/zoneinfo" -LOCALTIME_FILE = "/etc/localtime" -KERBEROS_CONF_FILE = "/etc/krb5.conf" -NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" -NTP_CONF_FILE = "/etc/ntp.conf" -MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" -SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" -RESOLV_CONF_FILE = "/etc/resolv.conf" -DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" -LIVE_MODE_FILE = "/etc/live" -ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" - -DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" -DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" -## - -## Base constants -MAX_PARTITION_SIZE = 16777216 # 16 TB -OS_PARTITION_SIZE = 4000 # 4 GB -SESSION_TIMEOUT = 1800 # 30 minutes -SERVER_AGENT_PORT = 50000 - -BOOT_PARTITION_LABEL = "GLUSTEROS" -DATA_PARTITION_LABEL = "GLUSTERDATA" -VOLUME_USER_DESCRIPTION = "Gluster Volume User" -SERVER_AGENT_RUN_USERNAME = "gluster" -INSTALLER_SERVER_NAME = "$installer$" - -GLUSTER_BASE_DIR = "/etc/glustermg" -GLUSTER_LUN_DIR = "/data" -REEXPORT_DIR = "/reexport" -NFS_EXPORT_DIR = "/nfs" -CIFS_EXPORT_DIR = "/cifs" -WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" -UPDATES_DIR = "/UPDATES" -TRANSPORT_HOME_DIR = "/transport" -GLUSTERFS_LOG_DIR = "/var/log/glusterfs" -LOG_DIR = "/var/log/glustermg" - -GLUSTER_UPDATES_FILE = "updates.xml" -INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" -INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" -LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" -PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" -## - -## Derived constants -GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" -GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" -VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" -SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" -DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" -INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME - -GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" -GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" -GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" -GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" -GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" -TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" -SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" -SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" -GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" -GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" - -VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" - -GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" -INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" -INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" -INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" - -SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" - -GENERAL_LOG_FILE = LOG_DIR + "/general.log" -INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" -PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log" -SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" -TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" -## - - -## Global variables -## TODO: These should be removed -DOWNLOAD_GLUSTER_UPDATE_PROCESS = None -DOWNLOAD_GLUSTER_UPDATE_LEVEL = None -DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None -DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None -REQUEST_MAP = {} -VERSION_DICTONARY = {} -## - -AWS_WEB_SERVICE_URL = "http://169.254.169.254/latest" -REAL_SAMBA_CONF_FILE = "/etc/samba/real.smb.conf" diff --git a/src/com.gluster.storage.management.server.scripts/src/GlusterdUtils.py b/src/com.gluster.storage.management.server.scripts/src/GlusterdUtils.py deleted file mode 100644 index 7c0e899c..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/GlusterdUtils.py +++ /dev/null @@ -1,250 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import Utils - -import ServerUtils - - -def getGlusterVolumeInfo(volumeName=None): - volumeNameList = None - if Utils.isString(volumeName): - volumeNameList = [volumeName] - if type(volumeName) == type([]): - volumeNameList = volumeName - - status = Utils.runCommand("gluster volume info", output=True, root=True) - if status["Status"] != 0: - Utils.log("Failed to execute 'gluster volume info' command") - return None - - volumeInfoDict = {} - volumeInfo = {} - volumeName = None - brickList = [] - for line in status['Stdout'].split("\n"): - if not line: - if volumeName and volumeInfo: - volumeInfo["Bricks"] = brickList - volumeInfoDict[volumeName] = volumeInfo - volumeInfo = {} - volumeName = None - brickList = [] - continue - - tokens = line.split(":") - if tokens[0].strip().upper() == "BRICKS": - continue - elif tokens[0].strip().upper() == "VOLUME NAME": - volumeName = tokens[1].strip() - volumeInfo["VolumeName"] = volumeName - elif tokens[0].strip().upper() == "TYPE": - volumeInfo["VolumeType"] = tokens[1].strip() - elif tokens[0].strip().upper() == "STATUS": - volumeInfo["VolumeStatus"] = tokens[1].strip() - elif tokens[0].strip().upper() == "TRANSPORT-TYPE": - volumeInfo["TransportType"] = tokens[1].strip() - elif tokens[0].strip().upper().startswith("BRICK"): - brickList.append(":".join(tokens[1:]).strip()) - - if volumeName and volumeInfo: - volumeInfoDict[volumeName] = volumeInfo - - if not volumeNameList: - return volumeInfoDict - - # remove unwanted volume info - for volumeName in list(set(volumeInfoDict.keys()) - set(volumeNameList)): - del volumeInfoDict[volumeName] - - return volumeInfoDict - - -def isVolumeRunning(volumeName): - if not volumeName: - return False - volumeInfo = getGlusterVolumeInfo(volumeName) - if not volumeInfo: - return False - status = volumeInfo[volumeName]["VolumeStatus"] - if not status: - return False - if status.upper() == "STARTED": - return True - return False - - -def isVolumeExist(volumeName): - if not volumeName: - return False - if getGlusterVolumeInfo(volumeName): - return True - return False - - -def peerProbe(serverName): - command = "gluster peer probe %s" % serverName - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def setAuthAllow(volumeName, authList, includeServers=True): - if not (volumeName and authList): - return False - vacl = [] - if includeServers: - for serverName in ServerUtils.getAllServerList(): - vacl += ServerUtils.getServerIpList(serverName) - vacl += authList - - command = "gluster volume set %s auth.allow %s" % (volumeName, ",".join(list(set(vacl)))) - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def volumeCreate(volumeName, volumeType, transportTypeList, brickList): - command = "gluster volume create %s" % volumeName - - if volumeType.upper() == "MIRROR": - command += " replica 2" - elif volumeType.upper() == "STRIPE": - command += " stripe 4" - - if "RDMA" in transportTypeList: - command += " transport rdma" - - command += " " + " ".join(brickList) - - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def volumeDelete(volumeName): - command = "gluster --mode=script volume delete %s" % volumeName - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def volumeLogFileName(volumeName, brick, logDir): - command = "gluster volume log filename %s %s %s" % (volumeName, brick, logDir) - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def startVolumeMigration(volumeName, sourcePath, destinationPath): - command = "gluster volume replace-brick %s %s %s start" % (volumeName, sourcePath, destinationPath) - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if lines[0].split()[-1] == "successfully": - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def stopVolumeMigration(volumeName, sourcePath, destinationPath): - command = "gluster volume replace-brick %s %s %s abort" % (volumeName, sourcePath, destinationPath) - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if lines[0].split()[-1] == "successful": - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def commitVolumeMigration(volumeName, sourcePath, destinationPath): - command = "gluster volume replace-brick %s %s %s commit" % (volumeName, sourcePath, destinationPath) - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if lines[0].split()[-1] == "successful": - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def getMigrationStatus(volumeName, sourcePath, destinationPath): - command = "gluster volume replace-brick %s %s %s status" % (volumeName, sourcePath, destinationPath) - status = Utils.runCommand(command, output=True, root=True) - if status['Status'] == 0 and status['Stdout']: - lines = status["Stdout"].split("\n") - if "Current file" in lines[0]: - return "started" - if "Migration complete" in lines[0]: - return "completed" - Utils.log("command [%s] returns unknown status:%s" % (command, lines[0])) - return "failed" - #if status['Status'] == 0 and status['Stdout']: - # for line in status['Stdout'].split('\n'): - # words = line.split() - # if words and words[0].upper() == "STATUS:": - # return " ".join(words[1:]).upper() - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return None - - -def volumeRebalanceStart(volumeName): - command = "gluster volume rebalance %s start" % volumeName - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if lines[0].split()[-1] == "successful": - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def volumeRebalanceStop(volumeName): - command = "gluster volume rebalance %s stop" % volumeName - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if lines[0].split()[0] == "stopped": - return True - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - - -def volumeRebalanceStatus(volumeName): - command = "gluster volume rebalance %s status" % volumeName - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - lines = status["Stdout"].split("\n") - if "rebalance not started" in lines[0]: - return "not started" - if "rebalance completed" in lines[0]: - return "completed" - return "running" - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False diff --git a/src/com.gluster.storage.management.server.scripts/src/NetworkUtils.py b/src/com.gluster.storage.management.server.scripts/src/NetworkUtils.py deleted file mode 100755 index 42e9892c..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/NetworkUtils.py +++ /dev/null @@ -1,483 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys - -if not "/usr/share/system-config-network/" in sys.path: - sys.path.append("/usr/share/system-config-network") - -import os -import tempfile -import Globals - -from Utils import * -#from netconfpkg.NCHardwareList import getHardwareList - -def readHostFile(fileName=None): - hostEntryList = [] - if not fileName: - fileName = "/etc/hosts" - try: - for line in open(fileName): - tokens = line.split("#")[0].strip().split() - if len(tokens) < 2: - continue - hostEntryList.append({tokens[0] : tokens[1:]}) - return hostEntryList - except IOError: - log("failed to read %s file" % fileName) - return None - - -def writeHostFile(hostEntryList, fileName=None): - if fileName: - hostFile = fileName - else: - hostFile = tempfile.mktemp(prefix="GSPSA") - try: - fp = open(hostFile, "w") - for host in hostEntryList: - fp.write("%s\t%s\n" % (host.keys()[0], " ".join(host.values()[0]))) - fp.close() - if hostFile == fileName: - return True - except IOError: - log("failed to write %s file" % hostFile) - return False - if runCommandFG("mv -f %s /etc/hosts" % hostFile, root=True) != 0: - log("failed to rename file %s to /etc/hosts" % hostFile) - return False - return True - - -def readResolvConfFile(fileName=None, includeLocalHost=False): - nameServerList = [] - domain = None - searchDomain = None - if not fileName: - fileName = Globals.RESOLV_CONF_FILE - try: - for line in open(fileName): - tokens = line.split("#")[0].strip().split() - if len(tokens) < 2: - continue - if tokens[0].upper() == "NAMESERVER": - if includeLocalHost == False and tokens[1] == "127.0.0.1": - continue - nameServerList.append(tokens[1]) - continue - if tokens[0].upper() == "DOMAIN": - domain = tokens[1:] - continue - if tokens[0].upper() == "SEARCH": - searchDomain = tokens[1:] - continue - return nameServerList, domain, searchDomain - except IOError: - log("failed to read %s file" % fileName) - return None, None, None - - -def writeResolvConfFile(nameServerList, domain, searchDomain, fileName=None, appendLocalHost=True): - if fileName: - resolvConfFile = fileName - else: - resolvConfFile = tempfile.mktemp(prefix="GSPSA") - try: - fp = open(resolvConfFile, "w") - if appendLocalHost: - fp.write("nameserver 127.0.0.1\n") - for nameServer in nameServerList: - fp.write("nameserver %s\n" % nameServer) - if domain: - fp.write("domain %s\n" % " ".join(domain)) - if searchDomain: - fp.write("search %s\n" % " ".join(searchDomain)) - fp.close() - if resolvConfFile == fileName: - return True - except IOError: - log("failed to write %s file" % resolvConfFile) - return False - if runCommandFG("mv -f %s %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE), root=True) != 0: - log("failed to rename file %s to %s" % (resolvConfFile, Globals.RESOLV_CONF_FILE)) - return False - return True - - -def readIfcfgConfFile(deviceName, root=""): - conf = {} - fileName = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) - try: - for line in open(fileName): - tokens = line.split("#")[0].split("=") - if len(tokens) != 2: - continue - conf[tokens[0].strip().lower()] = tokens[1].strip() - return conf - except IOError: - log("failed to read %s file" % fileName) - return None - - -def writeIfcfgConfFile(deviceName, conf, root="", deviceFile=None): - if not deviceFile: - deviceFile = "%s%s/ifcfg-%s" % (root, Globals.SYSCONFIG_NETWORK_DIR, deviceName) - if root: - ifcfgConfFile = deviceFile - else: - ifcfgConfFile = tempfile.mktemp(prefix="GSPSA") - try: - fp = open(ifcfgConfFile, "w") - for key in conf.keys(): - if key == "description": - fp.write("#%s=%s\n" % (key.upper(), conf[key])) - continue - if key in ['link', 'mode']: - continue - if conf["device"].startswith("bond") and key in ['hwaddr', 'master', 'slave']: - continue - if key == "slave" and conf['master']: - fp.write("SLAVE=yes\n") - continue - if key == "onboot": - if conf[key] == True: - fp.write("ONBOOT=yes\n") - elif isString(conf[key]) and conf[key].upper() == "YES": - fp.write("ONBOOT=yes\n") - else: - fp.write("ONBOOT=no\n") - continue - if not conf[key]: - continue - fp.write("%s=%s\n" % (key.upper(), conf[key])) - fp.close() - if ifcfgConfFile == deviceFile: - return True - except IOError: - log("failed to write %s file" % ifcfgConfFile) - return False - if runCommandFG("mv -f %s %s" % (ifcfgConfFile, deviceFile), root=True) != 0: - log("failed to rename file %s to %s" % (ifcfgConfFile, deviceFile)) - return False - return True - -def getNetDeviceDetail(deviceName): - deviceDetail = {} - deviceDetail['Name'] = deviceName - rv = runCommandFG("ifconfig %s" % deviceName, stdout=True, root=True) - if rv["Status"] != 0: - return False - for line in rv["Stdout"].split(): - tokens = line.strip().split(":") - if tokens[0].upper() == "ENCAP": - deviceDetail['Model'] = tokens[1].strip().upper() - break - - for line in rv["Stdout"].split("\n"): - if line.strip().startswith("inet addr:"): - tokens = line.strip().split(":") - if tokens[0].upper() == "INET ADDR": - try: - deviceDetail['Ip'] = tokens[1].strip().split()[0] - deviceDetail['Mask'] = tokens[-1].strip() - except IndexError: - pass - break - return deviceDetail - -def getNetDeviceGateway(deviceName): - rv = runCommand("route -n", output=True, root=True) - if rv["Status"] != 0: - return None - if not rv["Stdout"]: - return None - lines = [line for line in rv["Stdout"].split("\n") if line.find("UG") != -1 and line.find(deviceName)] - if not lines: - return None - line = lines[-1].split() - if line and len(line) > 1: - return line[1] - return None - -def getNetSpeed(deviceName): - rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) - if rv["Status"] != 0: - return False - for line in rv["Stdout"].split("\n"): - tokens = line.strip().split(":") - if tokens[0].upper() == "SPEED": - return tokens[1].strip().upper().split("MB")[0] - return None - -def getLinkStatus(deviceName): - return True - ## ethtool takes very long time to respond. So its disabled now - rv = runCommandFG("ethtool %s" % deviceName, stdout=True, root=True) - if rv["Status"] != 0: - return False - for line in rv["Stdout"].split("\n"): - tokens = line.strip().split(":") - if tokens[0].upper() == "LINK DETECTED": - if tokens[1].strip().upper() == "YES": - return True - else: - return False - return False - - -def getBondMode(deviceName, fileName=None): - if not fileName: - fileName = Globals.MODPROBE_CONF_FILE - try: - for line in open(fileName): - tokens = line.split("#")[0].split() - if len(tokens) < 4: - continue - if tokens[0].upper() == "OPTIONS" and tokens[1] == deviceName: - if tokens[2].startswith("mode="): - return tokens[2].split("=")[1] - if tokens[3].startswith("mode="): - return tokens[3].split("=")[1] - if tokens[4].startswith("mode="): - return tokens[4].split("=")[1] - if tokens[5].startswith("mode="): - return tokens[5].split("=")[1] - return None - except IOError: - log("failed to read %s file" % fileName) - return None - - -def setBondMode(deviceName, mode, fileName=None): - if not fileName: - fileName = Globals.MODPROBE_CONF_FILE - tempFileName = getTempFileName() - try: - fp = open(tempFileName, "w") - lines = open(fileName).readlines() - except IOError: - log("unable to open file %s" % Globals.MODPROBE_CONF_FILE) - return False - for line in lines: - tokens = line.split() - if len(tokens) > 1 and "OPTIONS" == tokens[0].upper() and "BOND" in tokens[1].upper() and deviceName == tokens[1]: - fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) - deviceName = None - continue - fp.write(line) - if deviceName: - fp.write("alias %s bonding\n" % deviceName) - fp.write("options %s max_bonds=2 mode=%s miimon=100\n" % (deviceName, mode)) - fp.close() - if runCommandFG(["mv", "-f", tempFileName, fileName], root=True) != 0: - log("unable to move file from %s to %s" % (tempFileName, fileName)) - return False - return True - -def getNetDeviceList(root=""): - netDeviceList = [] - for deviceName in os.listdir("/sys/class/net/"): - netDevice = {} - netDevice["device"] = None - netDevice["description"] = None - netDevice["hwaddr"] = None - netDevice["type"] = None - netDevice["onboot"] = None - netDevice["bootproto"] = None - netDevice["gateway"] = None - netDevice["peerdns"] = None - netDevice["autodns"] = None - netDevice["dns1"] = None - netDevice["dns2"] = None - netDevice["dns3"] = None - netDevice["master"] = None - netDevice["slave"] = None - netDevice["nmcontrolled"] = None - netDevice["link"] = None - netDevice["mode"] = None - - #netDevice["device"] = device.Name - netDevice["device"] = deviceName - #netDevice["description"] = device.Description - netDevice["description"] = deviceName - #netDevice["type"] = device.Type - netDevice["type"] = None - netDevice["link"] = getLinkStatus(deviceName) - netDevice["mode"] = getBondMode(deviceName, root + Globals.MODPROBE_CONF_FILE) - deviceDetail = getNetDeviceDetail(deviceName) - if deviceDetail.has_key('Model'): - netDevice["model"] = deviceDetail['Model'] - else: - netDevice["model"] = None - if deviceDetail.has_key('Ip'): - netDevice["ipaddr"] = deviceDetail['Ip'] - else: - netDevice["ipaddr"] = None - if deviceDetail.has_key('Mask'): - netDevice["netmask"] = deviceDetail['Mask'] - else: - netDevice["netmask"] = None - netDevice["speed"] = getNetSpeed(deviceName) - try: - netDevice["hwaddr"] = open("/sys/class/net/%s/address" % deviceName).read().strip() - except IOError: - pass - - netDeviceList.append(netDevice) - - conf = readIfcfgConfFile(deviceName, root) - if not conf: - continue - try: - netDevice["onboot"] = conf["onboot"] - except KeyError: - pass - try: - netDevice["bootproto"] = conf["bootproto"] - except KeyError: - pass - if conf.has_key("ipaddr") and conf["ipaddr"]: - netDevice["ipaddr"] = conf["ipaddr"] - try: - netDevice["netmask"] = conf["netmask"] - except KeyError: - pass - if conf.has_key("gateway") and conf["gateway"]: - netDevice["gateway"] = conf["gateway"] - else: - netDevice["gateway"] = getNetDeviceGateway(deviceName) - try: - netDevice["peerdns"] = conf["peerdns"] - except KeyError: - pass - try: - netDevice["autodns"] = conf["autodns"] - except KeyError: - pass - try: - netDevice["dns1"] = conf["dns1"] - except KeyError: - pass - try: - netDevice["dns2"] = conf["dns2"] - except KeyError: - pass - try: - netDevice["dns3"] = conf["dns3"] - except KeyError: - pass - try: - netDevice["master"] = conf["master"] - except KeyError: - pass - try: - netDevice["slave"] = conf["slave"] - except KeyError: - pass - try: - netDevice["nmcontrolled"] = conf["nmcontrolled"] - except KeyError: - pass - - return netDeviceList - - ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] - - ## bondDevices = [os.path.basename(device) for device in glob.glob("/sys/class/net/bond*")] - ## for deviceName in bondDevices: - ## if deviceName in linkedBondList: - ## if deviceName in sysConfigDeviceList: - ## deviceList[deviceName] = sysConfigDeviceList[deviceName] - ## else: - ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} - ## continue - ## if len(ethDevices) > 2: - ## deviceList[deviceName] = {'device':deviceName, 'onboot':'no', 'bootproto':'none'} - - -def configureDhcpServer(serverIpAddress, dhcpIpAddress): - tmpDhcpConfFile = tempfile.mktemp(prefix="GSPSA") - - serverPortString = "68" - try: - for arg in open("/proc/cmdline").read().strip().split(): - token = arg.split("=") - if token[0] == "dhcp": - serverPortString = token[1] - break - except IOError: - log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") - try: - serverPort = int(serverPortString) - except ValueError: - log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) - serverPort = 68 - - try: - fp = open(tmpDhcpConfFile, "w") - fp.write("bind-interfaces\n") - fp.write("except-interface=lo\n") - fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) - fp.write("dhcp-lease-max=1\n") - fp.write("dhcp-alternate-port=%s\n" % serverPort) - fp.write("dhcp-leasefile=%s\n" % Globals.DNSMASQ_LEASE_FILE) - #fp.write("server=%s\n" % serverIpAddress) - #fp.write("dhcp-script=/usr/sbin/server-info\n") - fp.close() - except IOError: - log(syslog.LOG_ERR, "unable to write dnsmasq dhcp configuration %s" % tmpDhcpConfFile) - return False - if runCommandFG("mv -f %s %s" % (tmpDhcpConfFile, Globals.DNSMASQ_DHCP_CONF_FILE), root=True) != 0: - log(syslog.LOG_ERR, "unable to copy dnsmasq dhcp configuration to %s" % Globals.DNSMASQ_DHCP_CONF_FILE) - return False - return True - - -def isDhcpServer(): - return os.path.exists(Globals.DNSMASQ_DHCP_CONF_FILE) - - -def getDhcpServerStatus(): - if runCommandFG("service dnsmasq status", root=True) == 0: - return True - return False - - -def startDhcpServer(): - if runCommandFG("service dnsmasq start", root=True) == 0: - return True - return False - - -def stopDhcpServer(): - if runCommandFG("service dnsmasq stop", root=True) == 0: - runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) - return True - return False - - -def restartDhcpServer(): - stopDhcpServer() - runCommandFG("rm -f %s" % Globals.DNSMASQ_LEASE_FILE, root=True) - return startDhcpServer() - - -def reloadDhcpServer(): - if runCommandFG("service dnsmasq reload", root=True) == 0: - return True - return False diff --git a/src/com.gluster.storage.management.server.scripts/src/Protocol.py b/src/com.gluster.storage.management.server.scripts/src/Protocol.py deleted file mode 100644 index ff073593..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Protocol.py +++ /dev/null @@ -1,438 +0,0 @@ -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import xml -import xml.parsers.expat -import xml.dom.minidom as MDOM -import os -import Globals -import copy -import Utils - -XML_STRING = 0 -XML_FILE = 1 - -class XDOM: - _domObj = None - - def __init__(self): - self._domObj = MDOM.Document() - return - - @classmethod - def getText(self, nodeList): - rc = "" - for node in nodeList: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc.strip() - - def parseString(self, requestString): - try: - self._domObj = MDOM.parseString(requestString) - except xml.parsers.expat.ExpatError, e: - Utils.log("XML string parse error: %s" % str(e)) - return False - return True - - def parseFile(self, fileName): - try: - self._domObj = MDOM.parse(fileName) - except IOError, e: - Utils.log("error reading file: %s" % str(e)) - return False - except xml.parsers.expat.ExpatError, e: - Utils.log("XML file %s parse error: %s" % (fileName, str(e))) - return False - return True - - def setDomObj(self, dom): - if dom and type(dom) != type([]): - self._domObj = dom - return True - return False - - def createTextNode(self, text): - if not self._domObj: - return False - if not text: - return False - return self._domObj.createTextNode(str(text)) - - def createTag(self, tag, text=None): - if not self._domObj: - return None - if tag == None: - return None - - tagE = self._domObj.createElement(str(tag)) - if text: - tagEText = self._domObj.createTextNode(str(text)) - tagE.appendChild(tagEText) - return tagE - - def addTag(self, tag): - if not self._domObj: - return False - if not tag: - return False - - self._domObj.appendChild(tag) - return True - - def createTagRoute(self, tagRoute, text=None): - if not tagRoute: - return False - - tagList = tagRoute.split(".") - tag = None - previousTag = None - for tagName in tagList[:-1]: - newTag = self.createTag(tagName, None) - if not tag: - tag = newTag - previousTag = newTag - continue - previousTag.appendChild(newTag) - previousTag = newTag - - if previousTag: - previousTag.appendChild(self.createTag(tagList[-1], text)) - else: - tag = self.createTag(tagList[-1], text) - return tag - - def appendTagRoute(self, tagRoute, value=None): - if not self._domObj: - return False - if not tagRoute: - return False - - parentTagE = self._domObj - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def setTextByTagRoute(self, tagRoute, tagValue): - if not self._domObj: - return None - - if not tagRoute: - return None - - tagE = self.getElementsByTagRoute(tagRoute) - if not tagE: - return False - - parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) - if not parentTagE: - return False - - parentTagE[0].childNodes.remove(tagE[0]) - parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) - return True - - def getElementsByTagRoute(self, tagRoute): - if not self._domObj: - return None - - if not tagRoute: - return None - - x = None - for tag in tagRoute.split("."): - if x is None: - x = self._domObj.getElementsByTagName(tag) - continue - if x == []: - break - x = x[0].getElementsByTagName(tag) - return x - - def getTextByTagRoute(self, tagRoute): - if not self._domObj: - return None - - x = self.getElementsByTagRoute(tagRoute) - if x: - return self.getText(x[0].childNodes) - return None - - def getElementsByTagName(self, name): - if not self._domObj: - return None - return self._domObj.getElementsByTagName(name) - - def writexml(self, fileName, indent="", addindent="", newl=""): - if not self._domObj: - return None - try: - fp = open(fileName, "w") - self._domObj.writexml(fp, indent, addindent, newl) - fp.close() - return True - except IOError: - return False - - def toString(self, indent=" ", newl="\n", encoding = None): - if not self._domObj: - return None - return self._domObj.toprettyxml(indent, newl, encoding) - - def toxml(self, encoding = None): - if not self._domObj: - return None - return self._domObj.toxml(encoding) - - def toprettyxml(self, indent=" ", newl="\n", encoding = None): - return self.toString(indent, newl, encoding) - - def getAttribute(self, attributeName): - if not attributeName: - return None - try: - return self.getElementsByTagName("command")[0].getAttribute(attributeName) - except IndexError: - return False - - def setAttribute(self, attributeName, attributeValue): - if not (attributeName and attributeValue): - return None - try: - return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue) - except IndexError: - return False - - def getRequestCommand(self): - return self.getAttribute("request") - - def getResponseCommand(self): - return self.getAttribute("response") - - def getResponseCode(self): - return self.getAttribute("response-code") - - def getMessageId(self): - return self.getAttribute("id") - - def getVersion(self): - return self.getAttribute("version") - - def getRequestAction(self): - return self.getAttribute("action") - - def setVersion(self, value): - return self.setAttribute("version", value) - - def setRequestAction(self, value): - return self.setAttribute("action", value) - - def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - commandTag = self._domObj.createElement("command") - commandTag.setAttribute("response", command) - commandTag.setAttribute("response-code", responseCode) - commandTag.setAttribute("id", id) - commandTag.setAttribute("version", version) - return commandTag -##--end of XDOM - -class RequestXml(XDOM): - def __init__(self, requestString, type=None): - if None == requestString: - XDOM.__init__(self) - return - try: - if None == type: - if os.path.isfile(requestString): - self._domObj = MDOM.parse(requestString) - else: - self._domObj = MDOM.parseString(requestString) - elif XML_FILE == type: - self._domObj = MDOM.parse(requestString) - elif XML_STRING == type: - self._domObj = MDOM.parseString(requestString) - except IOError: - XDOM.__init__(self) - except xml.parsers.expat.ExpatError: - XDOM.__init__(self) - -##--end of RequestXML - -class ResponseXml(XDOM): - _commandTag = None - def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - XDOM.__init__(self) - if command and responseCode and id: - self._commandTag = self.createCommandTag(command, responseCode, id, version) - self._domObj.appendChild(self._commandTag) - - def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - if command and responseCode and id: - self._commandTag = self.createCommandTag(command, responseCode, id, version) - self._domObj.appendChild(self._commandTag) - return True - return False - - def append(self, tagName, tagValue=None): - if not self._commandTag: - return False - tag = self.createTag(tagName, tagValue) - if tag: - self._commandTag.appendChild(tag) - return True - return False - - def appendTag(self, tag): - if not tag: - return False - if not self._commandTag: - return False - self._commandTag.appendChild(tag) - return True - - def appendTagRoute(self, tagRoute, value=None): - if not self._commandTag: - return False - if not tagRoute: - return False - - parentTagE = self._commandTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def appendTagRouteOld(self, tagRoute, value=None): - if not tagRoute: - return False - if not self._commandTag: - return False - - tmpTagRoute = "" - previousTagE = self._commandTag - tagE = None - for tagName in tagRoute.split("."): - if not tmpTagRoute: - tagE = self.getElementsByTagRoute("command." + tagName) - else: - tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName) - if not tagE: - break - if len(tagE) != 1: - return False - previousTagE = tagE[0] - if not tmpTagRoute: - tmpTagRoute = tagName - else: - tmpTagRoute = tmpTagRoute + "." + tagName - - if tmpTagRoute == tagRoute: - return False - newTagRoute = tagRoute[len(tmpTagRoute):] - if newTagRoute[0] == '.': - newTagRoute = newTagRoute[1:] - - if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE: - return False - previousTagE.appendChild(self.createTagRoute(newTagRoute, value)) - return True -##--end of ResponseXml - -def test(): - #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume") - requestStr = ''' - -movies1 -cluster mirror -512000 -zresearch -192.168.20.* -192.168.30.* - -no - - -no - - -no - - -''' - - requestXml = RequestXml(requestStr) - print requestXml.getAttribute("") - -def test1(): - rs = ResponseXml("create-volume", "OK", "xyz") - rs.appendTagRoute("volume.detail.name", "music") - print rs.toprettyxml() - rs.append("volume", "data") - print rs.toprettyxml() - rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1") - print rs.toprettyxml() - print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::") - print rs.toprettyxml() - - print rs.getTextByTagRoute("command.volume.detail") - -def test2(): - rs = ResponseXml("download-volume-logs", "OK", "xyz") - te = rs.createTag("interface", None) - te.appendChild(rs.createTag("device", "DEVICE1")) - te.appendChild(rs.createTag("description", "my device one")) - rs.appendTag(te) - - te = rs.createTag("interface", None) - te.appendChild(rs.createTag("device", "DEVICE2")) - te.appendChild(rs.createTag("description", "my device two")) - rs.appendTag(te) - print rs.toprettyxml() - diff --git a/src/com.gluster.storage.management.server.scripts/src/RRDUtils.py b/src/com.gluster.storage.management.server.scripts/src/RRDUtils.py deleted file mode 100644 index 1ad0deee..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/RRDUtils.py +++ /dev/null @@ -1,72 +0,0 @@ -import rrdtool -import os -from socket import gethostname -from itertools import groupby - -class RRD: - def __init__ (self): - self.COLORS = [0xff7777, 0x7777ff, 0x55ff55, 0xffcc77, 0xff77ff, 0x77ffff,0xffff77, 0x55aaff] - self.HOST = gethostname() - self.DIR = "/var/lib/collectd" - - def fade_component(self, component): - return ((component + 255 * 5) / 6) - - def fade_color(self, color): - r = 0; - for i in [0,1,2]: - shft = (i * 8) - component = ((color >> shft) & 255) - r |= (self.fade_component(component) << shft) - return r - - def generate_pngs(self): - - rrdlist = os.popen ("find %s -type f -name '*.rrd'" % self.DIR) - - for rrd in rrdlist: - self.dss = [] - self.defs = "" - - rrdinfo = rrdtool.info(rrd.strip()) - - for key in rrdinfo.keys(): - if key.split('[')[0] == 'ds': - self.dss.append(key.split('[')[1].split(']')[0]) - self.dss.sort() - - self.dss = [a for a,b in groupby(self.dss)] - - for ds in self.dss: - self.defs = self.defs + " DEF:%s_avg=%s:%s:AVERAGE " % (ds, rrd.strip(), ds) - self.defs = self.defs + " DEF:%s_max=%s:%s:MAX " % (ds, rrd.strip(), ds) - - j = 0 - for ds in self.dss: - color = self.COLORS[j % len(self.COLORS)] - j = j + 1 - faded_color = self.fade_color(color) - self.defs = self.defs + " AREA:%s_max#%06x " % (ds, faded_color) - - j = 0 - for ds in self.dss: - color = self.COLORS[j % len(self.COLORS)] - j = j + 1 - self.defs = self.defs + " LINE2:%s_avg#%06x:%s " % (ds, color, ds) - self.defs = self.defs + " GPRINT:%s_avg:AVERAGE:%%5.1lf%%sAvg " % ds - self.defs = self.defs + " GPRINT:%s_max:MAX:%%5.1lf%%sMax " % ds - - for span in ['1hour', '1day', '1week', '1month']: - os.system ("mkdir -p %s/%s" % (self.DIR, self.HOST)) - image = os.path.dirname(rrd.strip()) + "-" + span + ".png" - cmd = "rrdtool graph " + image + " -t \"%s %s\"" % (os.path.dirname(rrd.strip()), span) + " --imgformat PNG --width 600 --height 100 --start now-" + span + " --end now --interlaced " + self.defs + " >/dev/null 2>&1" - os.system(cmd) - - -def main (): - - rrd = RRD () - rrd.generate_pngs () - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/ServerUtils.py b/src/com.gluster.storage.management.server.scripts/src/ServerUtils.py deleted file mode 100644 index 1fec994c..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/ServerUtils.py +++ /dev/null @@ -1,308 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import re -import subprocess -import glob -import Globals -from Protocol import * -from Utils import * - -def isValidServer(serverName): - for profile in getProfileList(): - if profile.ProfileName == "default" and profile.Active: - if serverName == profile.DNS.Hostname: - return True - return False - -def getHostname(): - for profile in getProfileList(): - if profile.ProfileName == "default" and profile.Active: - return profile.DNS.Hostname - return None - -def getDomainName(): - try: - domainName = open(Globals.DOMAINNAME_FILE).read() - except IOError: - return None - return domainName.split()[0] - -def replaceServerIp(fileName, findWhat, replaceWith): - try: - data = open(fileName).read() - fp = open(fileName, "w") - fp.write(re.sub(findWhat, replaceWith, data)) - fp.close() - return True - except IOError: - return False - except ValueError: - return False - except OSError: - return False - -def serverName2IpAddress(serverName): - command = "dig %s | grep '^%s'" % (serverName, serverName) - ps = subprocess.Popen(command, - shell=True, - stdout=subprocess.PIPE, - stdin=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=True) - ipAddress = serverName - if ps.wait() == 0: - output = ps.communicate() - ipAddress = output[0].split()[-1] - return ipAddress - -def getInstallerIp(): - if not os.path.exists(Globals.INSTALLER_INFO_FILE): - return None - try: - for line in open(Globals.INSTALLER_INFO_FILE): - tokens = line.split("=") - if tokens[0] == "IP-ADDRESS": - return tokens[1].split(",")[0].strip() - except IOError: - syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.INSTALLER_INFO_FILE) - return False - -def setInstallerIp(installerIp): - try: - open(Globals.INSTALLER_INFO_FILE, "w").write("IP-ADDRESS=%s\n" % installerIp) - return True - except IOError: - log(syslog.LOG_ERR, "unable to create %s file" % Globals.INSTALLER_INFO_FILE) - return False - -def getCurrentServerName(): - try: - for line in open(Globals.SYSCONFIG_NETWORK_FILE): - tokens = line.split("=") - if tokens[0] == "HOSTNAME": - return tokens[1].strip() - except IOError: - syslog.syslog(syslog.LOG_ERR, "unable to read %s file" % Globals.SYSCONFIG_NETWORK_FILE) - return False - -def getLastAccessedNetwork(serverName): - lastAccessedNetworkFile = ("/%s/servers/%s/%s" % - (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) - try: - return open(lastAccessedNetworkFile).read().strip() - except IOError: - log(syslog.LOG_ERR, "failed to read last accessed network file %s" % lastAccessedNetworkFile) - pass - return False - -def setLastAccessedNetwork(serverName, ipAddress): - lastAccessedNetworkFile = ("/%s/servers/%s/%s" % - (Globals.GLUSTER_CONF_DIR, serverName, Globals.LAST_ACCESSED_NETWORK_FILE)) - try: - open(lastAccessedNetworkFile, "w").write(ipAddress.strip() + "\n") - except IOError: - log(syslog.LOG_ERR, "failed to write last accessed network file %s" % lastAccessedNetworkFile) - return False - return True - -def getServerIpList(serverName, preferredNetworkOnly=False): - networkXmlFile = ("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) - configDom = XDOM() - if not configDom.parseFile(networkXmlFile): - log(syslog.LOG_ERR, "failed to read %s file" % networkXmlFile) - return None - preferredNetwork = configDom.getTextByTagRoute("preferred-network") - ipList = [] - interfaceDom = XDOM() - for tagE in configDom.getElementsByTagName("interface"): - interfaceDom.setDomObj(tagE) - deviceName = interfaceDom.getTextByTagRoute("device") - hostIp = interfaceDom.getTextByTagRoute("ipaddr") - if not hostIp: - continue - if preferredNetworkOnly: - if preferredNetwork.upper() == "ANY" or preferredNetwork.upper() == deviceName.upper(): - ipList.append(hostIp) - else: - ipList.append(hostIp) - if preferredNetworkOnly: - lastAccessedNetworkIp = getLastAccessedNetwork(serverName) - if lastAccessedNetworkIp in ipList: - ipList.remove(lastAccessedNetworkIp) - ipList = [lastAccessedNetworkIp] + ipList - return ipList - -def getServerPreferredIpList(serverName): - return getServerIpList(serverName, True) - -def getExecuteServerList(serverList): - executeServerList = {} - for serverName in serverList: - if serverName == Globals.INSTALLER_SERVER_NAME: - installerIp = getInstallerIp() - if installerIp: - executeServerList[serverName] = [installerIp] - continue - executeServerList[serverName] = getServerPreferredIpList(serverName) - return executeServerList - -def getAllServerList(): - serverList = [] - for filePath in glob.glob("%s/servers/*" % Globals.GLUSTER_CONF_DIR): - if os.path.isdir(filePath): - serverList.append(os.path.basename(filePath)) - try: - serverList.remove(Globals.INSTALLER_SERVER_NAME) - except ValueError: - pass - return serverList - -def getServerNetworkConfigFromLocalFile(serverName): - configDom = XDOM() - configDom.parseFile("%s/servers/%s/network.xml" % (Globals.GLUSTER_CONF_DIR, serverName)) - return configDom - -def updateServerNetworkConfigXmlFile(serverName, serverNetworkDom): - configDom = XDOM() - serverTag = serverNetworkDom.getElementsByTagRoute("server")[0] - configDom.setDomObj(serverTag) - if not configDom.writexml("%s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)): - log("Faild to write xml file %s/%s/network.xml" % (Globals.SERVER_VOLUME_CONF_DIR, serverName)) - -def compareServerNetworkDom(serverNetworkDomA, serverNetworkDomB, requestFlag=True): - command = "command.server." - if not requestFlag: - command = "" - sourceServer = {} - tagText = serverNetworkDomA.getTextByTagRoute("name") - if not tagText: - taxText = None - sourceServer["name"] = tagText - tagText = serverNetworkDomA.getTextByTagRoute("domain-name") - if not tagText: - tagText = None - sourceServer["domain-name"] = tagText - tagText = serverNetworkDomA.getTextByTagRoute("search-domain") - if not tagText: - tagText = None - sourceServer["search-domain"] = tagText - tagText = serverNetworkDomA.getTextByTagRoute("dns1") - if not tagText: - tagText = None - sourceServer["dns1"] = tagText - tagText = serverNetworkDomA.getTextByTagRoute("dns2") - if not tagText: - tagText = None - sourceServer["dns2"] = tagText - tagText = serverNetworkDomA.getTextByTagRoute("dns3") - if not tagText: - tagText = None - sourceServer["dns3"] = tagText - for tagE in serverNetworkDomA.getElementsByTagRoute("interface"): - interfaceDom = XDOM() - interfaceDom.setDomObj(tagE) - sourceServerList = {} - tagText = interfaceDom.getTextByTagRoute("description") - if not tagText: - tagText = None - sourceServerList["description"] = tagText - tagText = interfaceDom.getTextByTagRoute("hwaddr") - if not tagText: - tagText = None - sourceServerList["hwaddr"] = tagText - tagText = interfaceDom.getTextByTagRoute("onboot") - if not tagText: - tagText = None - sourceServerList["onboot"] = tagText - tagText = interfaceDom.getTextByTagRoute("bootproto") - if not tagText: - tagText = None - sourceServerList["bootproto"] = tagText - tagText = interfaceDom.getTextByTagRoute("ipaddr") - if not tagText: - tagText = None - sourceServerList["ipaddr"] = tagText - tagText = interfaceDom.getTextByTagRoute("netmask") - if not tagText: - tagText = None - sourceServerList["netmask"] = tagText - tagText = interfaceDom.getTextByTagRoute("gateway") - if not tagText: - tagText = None - sourceServerList["gateway"] = tagText - sourceServer[interfaceDom.getTextByTagRoute("device")] = sourceServerList - objServer = {} - tagText = serverNetworkDomB.getTextByTagRoute(command + "name") - if not tagText: - taxText = None - objServer["name"] = tagText - tagText = serverNetworkDomB.getTextByTagRoute(command + "domain-name") - if not tagText: - tagText = None - objServer["domain-name"] = tagText - tagText = serverNetworkDomB.getTextByTagRoute(command + "search-domain") - if not tagText: - tagText = None - objServer["search-domain"] = tagText - tagText = serverNetworkDomB.getTextByTagRoute(command + "dns1") - if not tagText: - tagText = None - objServer["dns1"] = tagText - tagText = serverNetworkDomB.getTextByTagRoute(command + "dns2") - if not tagText: - tagText = None - objServer["dns2"] = tagText - tagText = serverNetworkDomB.getTextByTagRoute(command + "dns3") - if not tagText: - tagText = None - objServer["dns3"] = tagText - for tagE in serverNetworkDomB.getElementsByTagRoute(command + "interface"): - interfaceDom = XDOM() - interfaceDom.setDomObj(tagE) - objServerList = {} - tagText = interfaceDom.getTextByTagRoute("description") - if not tagText: - tagText = None - objServerList["description"] = tagText - tagText = interfaceDom.getTextByTagRoute("hwaddr") - if not tagText: - tagText = None - objServerList["hwaddr"] = tagText - tagText = interfaceDom.getTextByTagRoute("onboot") - if not tagText: - tagText = None - objServerList["onboot"] = tagText - tagText = interfaceDom.getTextByTagRoute("bootproto") - if not tagText: - tagText = None - objServerList["bootproto"] = tagText - tagText = interfaceDom.getTextByTagRoute("ipaddr") - if not tagText: - tagText = None - objServerList["ipaddr"] = tagText - tagText = interfaceDom.getTextByTagRoute("netmask") - if not tagText: - tagText = None - objServerList["netmask"] = tagText - tagText = interfaceDom.getTextByTagRoute("gateway") - if not tagText: - tagText = None - objServerList["gateway"] = tagText - objServer[interfaceDom.getTextByTagRoute("device")] = objServerList - return sourceServer == objServer diff --git a/src/com.gluster.storage.management.server.scripts/src/Utils.py b/src/com.gluster.storage.management.server.scripts/src/Utils.py deleted file mode 100644 index 3408c14a..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/Utils.py +++ /dev/null @@ -1,1059 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import os -import re -import socket -import struct -import syslog -import subprocess -#import spwd -import time -#import uuid -import tempfile -import grp -import pwd -import inspect -from datetime import datetime -import urllib - -import Globals -import Protocol - -RUN_COMMAND_ERROR = -1024 -LOG_SYSLOG = 1 -SYSLOG_REQUIRED = False -LOG_FILE_NAME = None -LOG_FILE_OBJ = None - - -def _getLogCode(priority): - if syslog.LOG_EMERG == priority: - return "M" - elif syslog.LOG_ALERT == priority: - return "A" - elif syslog.LOG_CRIT == priority: - return "C" - elif syslog.LOG_ERR == priority: - return "E" - elif syslog.LOG_WARNING == priority: - return "W" - elif syslog.LOG_NOTICE == priority: - return "N" - elif syslog.LOG_INFO == priority: - return "I" - elif syslog.LOG_DEBUG == priority: - return "D" - else: # UNKNOWN - return "X" - - -def setLogFile(fileName): - global LOG_FILE_NAME - - if fileName: - LOG_FILE_NAME = fileName - return True - return False - - -def closeLog(): - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - if SYSLOG_REQUIRED: - syslog.closelog() - SYSLOG_REQUIRED = False - return True - - if LOG_FILE_OBJ: - try: - LOG_FILE_OBJ.close() - LOG_FILE_OBJ = None - except IOError, e: - sys.stderr.write("Failed to close file: %s\n" % e) - return False - return True - - -def openLog(fileName=None): - global LOG_FILE_NAME - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - if fileName == LOG_SYSLOG: - syslog.openlog(os.path.basename(sys.argv[0])) - SYSLOG_REQUIRED = True - return True - - if fileName: - LOG_FILE_NAME = fileName - - if not LOG_FILE_NAME: - return False - - closeLog() - - try: - LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") - except IOError, e: - sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) - return False - return True - -def record(priority, message=None): - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - stack = inspect.stack()[1] - if stack[3] == "": - prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3]) - else: - prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3]) - - if type(priority) == type("") or type(priority) == type(u""): - logPriority = syslog.LOG_INFO - logMessage = priority - else: - logPriority = priority - logMessage = message - - if SYSLOG_REQUIRED: - syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage)) - return - - fp = sys.stderr - if LOG_FILE_OBJ: - fp = LOG_FILE_OBJ - - fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage)) - if logMessage[-1] != '\n': - fp.write("\n") - fp.flush() - return - - -def trace(message): - if message: - log(syslog.LOG_DEBUG, message) - - -def isString(value): - return (type(value) == type("") or type(value) == type(u"")) - - -def getTempFileName(): - filedesc, filename = tempfile.mkstemp(prefix="GSP_") - os.close(filedesc) - return filename - - -def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, - shell=False, root=None): - log("runCommandBG(): Trying to execute command [%s]" % command) - - if shell: - if not isString(command): - return None - else: - if isString(command): - command = command.split() - - if root == True: - if shell: - command = "sudo " + command - else: - command = ['sudo'] + command - elif isString(root): - if shell: - command = "sudo -u " + root + " " + command - else: - command = ['sudo', '-u', root] + command - - if not stdinFileObj: - stdinFileObj=subprocess.PIPE - if not stdoutFileObj: - stdoutFileObj=subprocess.PIPE - if not stderrFileObj: - stderrFileObj=subprocess.PIPE - - try: - process = subprocess.Popen(command, - bufsize=-1, - stdin=stdinFileObj, - stdout=stdoutFileObj, - stderr=stderrFileObj, - shell=shell) - return process - except OSError, e: - log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) - return None - - -def runCommand(command, - input='', output=False, - shell=False, root=None): - rv = {} - rv["Status"] = RUN_COMMAND_ERROR - rv["Stdout"] = None - rv["Stderr"] = None - - try: - stdinFileName = getTempFileName() - stdinFileObj = open(stdinFileName, "w") - stdinFileObj.write(input) - stdinFileObj.close() - stdinFileObj = open(stdinFileName, "r") - - stdoutFileName = getTempFileName() - stdoutFileObj = open(stdoutFileName, "w") - - stderrFileName = getTempFileName() - stderrFileObj = open(stderrFileName, "w") - except IOError, e: - log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) - if output: - return rv - return rv["Status"] - - stdoutContent = None - stderrContent = None - - process = runCommandBG(command, - stdinFileObj=stdinFileObj, - stdoutFileObj=stdoutFileObj, - stderrFileObj=stderrFileObj, - shell=shell, root=root) - if process: - rv['Status'] = process.wait() - rv['Stdout'] = open(stdoutFileName).read() - rv['Stderr'] = open(stderrFileName).read() - - os.remove(stdinFileName) - os.remove(stdoutFileName) - os.remove(stderrFileName) - - log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) - - if output: - return rv - return rv["Status"] - - -def runCommandFG(command, stdout=False, stderr=False, - shell=False, root=None): - if stdout or stderr: - output = True - else: - output = False - return runCommand(command, output=output, shell=shell, root=root) - - -def IP2Number(ipString): - try: - return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) - except socket.error: - return None - except TypeError: - return None - except struct.error: - return None - - -def Number2IP(number): - try: - return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) - except socket.error: - return None - except AttributeError: - return None - except ValueError: - return None - - -def computeHostName(hostName): - if not hostName: - return False - - hostPrefix = "" - for i in range(len(hostName), 0, -1): - pos = i - 1 - if hostName[pos].isdigit(): - continue - break - hostPrefix = hostName[:pos+1] - try: - hostIndex = int(hostName[pos+1:]) - except ValueError: - hostIndex = 0 - # TODO: Check the availablity of the (server) name - return "%s%s" % (hostPrefix, hostIndex + 1) - - -def daemonize(): - try: - pid = os.fork() - if pid > 0: - # exit first parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - - # do second fork - try: - pid = os.fork() - if pid > 0: - # exit from second parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # redirect standard file descriptors - sys.stdout.flush() - sys.stderr.flush() - si = file("/dev/null", 'r') - so = file("/dev/null", 'a+') - se = file("/dev/null", 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - return True - - -def getDownloadStatus(fileName): - try: - lines = [line for line in open(fileName) - if "saved" in line or "%" in line] - except IOError: - return 0 - if not lines: - return 0 - if "saved" in lines[-1]: - return 100 - return lines[-1].split("%")[0].split()[-1] - - -def getMeminfo(): - """-> dict of data from meminfo (str:int). - Values are in kilobytes. - """ - import re - re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB' ) - result = {} - for line in open('/proc/meminfo'): - match = re_parser.match(line) - if not match: - continue # skip lines that don't parse - key, value = match.groups(['key', 'value']) - result[key] = int(value) - result['MemUsed'] = (result['MemTotal'] - result['MemFree']) - return result - - -def getCpuUsage(): - """-> dict of cpuid : (usertime, nicetime, systemtime, idletime) - cpuid "cpu" means the total for all CPUs. - cpuid "cpuN" means the value for CPU N. - """ - wanted_records = [line for line in open('/proc/stat') if - line.startswith('cpu')] - result = {} - for cpuline in wanted_records: - fields = cpuline.split()[:5] - data = map(int, fields[1:]) - result[fields[0]] = tuple(data) - return result - -def _getCpuStatList(): - try: - fp = open("/proc/stat") - cpuStatList = map(float, fp.readline().split()[1:]) - fp.close() - return cpuStatList - except IOError, e: - Utils.log("Failed to open /proc/stat: %s" % str(e)) - return None - -def getCpuUsageAvg(): - st1 = _getCpuStatList() - time.sleep(2) - st2 = _getCpuStatList() - if not (st1 and st2): - return None - delta = [st2[i] - st1[i] for i in range(len(st1))] - cpuPercent = sum(delta[:3]) / delta[3] * 100.0 - return str('%.4f' % cpuPercent) - -def getLoadavg(): - try: - loadavgstr = open('/proc/loadavg', 'r').readline().strip() - except IOError: - syslog.syslog(syslog.LOG_ERR, "failed to find cpu load") - return None - - data = map(float, loadavgstr.split()[1:]) - # returns 1 minute load average - return data[0] - - -def getInfinibandPortStatus(): - - """ Check for availability of infiniband port - and return which port is active in a key pair value - """ - - # Check for existence of infiniband ports - value = os.popen ("ls /sys/class/infiniband").readline().strip() - - if not value: - return None - - portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split() - - portkeys = {} - - for port in portlist: - value = os.popen ("cat %s/state" % - port.strip()).readline().split(':')[1].strip() - portkeys[port.strip()] = value - - return portkeys - - -def getServerCount(): - try: - return int(open(Globals.SERVER_COUNT_FILE).read().strip()) - except IOError: - log("failed to read file %s" % Globals.SERVER_COUNT_FILE) - return 1 - except ValueError: - log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE) - return 1 - - -def setServerCount(count): - try: - open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count) - return True - except IOError: - log("failed to write file %s" % Globals.SERVER_COUNT_FILE) - return False - - -def getInstalledServerCount(): - try: - return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip()) - except IOError: - log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return 1 - except ValueError: - log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return 1 - - -def setInstalledServerCount(count): - try: - open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count) - return True - except IOError: - log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return False - - -def getLastInstalledServerIpList(): - ipList = {} - networkDom = Protocol.XDOM() - if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE): - log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE) - for tagE in networkDom.getElementsByTagRoute("server.interface"): - interfaceDom = Protocol.XDOM() - interfaceDom.setDomObj(tagE) - ipAddress = interfaceDom.getTextByTagRoute("ipaddr") - if ipAddress: - ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress - return ipList - - -def getFreeIpAddress(device=None): - serverCount = getServerCount() - installedServerCount = getInstalledServerCount() - if serverCount == installedServerCount: - return None - - availableServerCount = serverCount - installedServerCount - ipList = getLastInstalledServerIpList() - - if not ipList: - return None - - if device: - if device not in ipList.keys(): - return None - deviceIpAddress = ipList[device] - else: - deviceIpAddress = ipList.values()[0] - ipNumber = IP2Number(deviceIpAddress) - - for i in range((ipNumber + availableServerCount), ipNumber, -1): - ipAddress = Number2IP(i) - if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0: - return ipAddress - return None - - -def getPasswordHash(userName): - try: - #return spwd.getspnam(userName).sp_pwd - return "Not implimented" - except KeyError: - return None - - -def getTransactionKey(): - try: - tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',') - except IOError: - return None, None - return tokens - - -def generateSignature(): - #return str(uuid.uuid4()) + ('--%f' % time.time()) - return ('--%f' % time.time()) - - -def getSignature(): - try: - return open(Globals.SIGNATURE_FILE).read().strip() - except IOError: - log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE) - return False - - -def storeSignature(signature, fileName=Globals.SIGNATURE_FILE): - try: - open(fileName, "w").write(signature + "\n") - except IOError: - log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName)) - return False - return True - - -def isUserExist(userName): - try: - grp.getgrnam(userName).gr_gid - return True - except KeyError: - pass - try: - pwd.getpwnam(userName).pw_uid - return True - except KeyError: - pass - return False - - -def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE): - userInfo = {} - userInfo["UserId"] = None - userInfo["Password"] = None - try: - for line in open(fileName): - line = line.strip() - k = line[:line.index("=")] - v = line[line.index("=") + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "GSN_ID": - userInfo["UserId"] = v - if k.upper() == "GSN_PASSWORD": - userInfo["Password"] = v - except IOError, e: - log("Failed to read file %s: %s" % (fileName, e)) - return userInfo - - -def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE): - try: - fp = open(fileName, "w") - fp.write("GSN_ID=%s\n" % userInfo["UserId"]) - fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"]) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (fileName, e)) - return False - - -def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE): - versionInfo = {} - versionInfo["Version"] = None - versionInfo["Update"] = None - try: - lines = open(Globals.GLUSTER_VERSION_FILE).readlines() - for line in open(fileName): - line = line.strip() - k = line[:line.index("=")] - v = line[line.index("=") + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "VERSION": - versionInfo["Version"] = v - if k.upper() == "UPDATE": - versionInfo["Update"] = v - except IOError, e: - log("Failed to read file %s: %s" % (fileName, e)) - return versionInfo - - -def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE): - if isString(versionInfo): - tokens = versionInfo.strip().split(".") - if len(tokens) < 2: - log("Invalid version format %s. Expecting .." % versionInfo) - return False - version = ".".join(tokens[:2]) - update = ".".join(tokens[2:]) - if not update: - update = "0" - else: - version = versionInfo["Version"] - update = versionInfo["Update"] - try: - fp = open(fileName, "w") - fp.write("VERSION=%s\n" % version) - fp.write("UPDATE=%s\n" % update) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (fileName, e)) - return False - - -def getGlusterUpdateDom(serverVersion): - errorMessage = "" - updateInfoDom = None - try: - baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip() - except IOError, e: - log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e)) - errorMessage = "Failed to read update site file" - return updateInfoDom, errorMessage - - try: - url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE) - connection = urllib.urlopen(url) - if connection.getcode() != 200: - connection.close() - errorMessage = "Error received from server to open URL %s" % url - return updateInfoDom, errorMessage - updateInfoString = connection.read() - connection.close() - except IOError, e: - log("Failed to get update information from URL %s: %s" % (url, e)) - errorMessage = "Error getting update information" - return updateInfoDom, errorMessage - - updateInfoDom = Protocol.XDOM() - if not updateInfoDom.parseString(updateInfoString): - log("XML parse error on update information content [%s]" % updateInfoString) - errorMessage = "Parse error on update information" - updateInfoDom = None - return updateInfoDom, errorMessage - - -def removeFile(fileName, root=False): - if root: - if runCommand("rm %s" % fileName, root=True) == 0: - return True - return False - try: - os.remove(fileName) - return True - except OSError, e: - log("Failed to remove file %s: %s" % (fileName, e)) - return False - - -def isLiveMode(): - return os.path.exists(Globals.LIVE_MODE_FILE) - -def convertKbToMb(kb): - return kb / 1024.0 - - -def getIPIndex(indexFile): - try: - fp = open(indexFile) - line = fp.readline() - fp.close() - index = int(line) - except IOError: - index = 0 - except ValueError: - index = False - return index - -def setIPIndex(index, indexFile): - try: - fp = open(indexFile, "w") - fp.write(str(index)) - fp.close() - except IOError: - return False - return True - -def IP2Number(ipString): - try: - return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) - except socket.error: - return None - except TypeError: - return None - except struct.error: - return None - -def Number2IP(number): - try: - return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) - except socket.error: - return None - except AttributeError: - return None - except ValueError: - return None - -def hasEntryFoundInFile(searchString, dnsEntryFileName): - try: - addServerEntryList = open(dnsEntryFileName).read().split() - except IOError: - return None - if searchString in addServerEntryList: - return True - return False - - -def computeIpAddress(ipAddress, startIp, endIp): - startIpNumber = IP2Number(startIp) - endIpNumber = IP2Number(endIp) - if not ipAddress: - return startIp - nextIpNumber = IP2Number(ipAddress) - while True: - nextIpNumber = nextIpNumber + 1 - ipAddress = Number2IP(nextIpNumber) - rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) - if type(rv) == type(True): - return False - if rv != 0: - break - - if nextIpNumber >= startIpNumber and nextIpNumber <= endIpNumber: - return ipAddress - - nextIpNumber = IP2Number(startIp) - while True: - ipAddress = Number2IP(nextIpNumber) - nextIpNumber = nextIpNumber + 1 - rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) - if type(rv) == type(True): - return False - if rv != 0: - break - - if IP2Number(ipAddress) >= startIpNumber and IP2Number(ipAddress) <= endIpNumber: - return ipAddress - return False - - -def setHostNameAndIp(hostName, ipAddress, lastAddServerDetailFile): - try: - fp = open(lastAddServerDetailFile, "w") - fp.write("HOSTNAME=" + hostName + "\n") - fp.write("IPADDRESS=" + ipAddress); - fp.close() - except IOError: - return False - return True - -def getPort(): - try: - fd = open(Globals.PORT_FILE, "r") - portString = fd.readline() - fd.close() - port = int(portString) - except IOError: - port = Globals.DEFAULT_PORT - 2 - except ValueError: - port = Globals.DEFAULT_PORT - 2 - return port - -def setPort(port): - try: - fd = open(Globals.PORT_FILE, "w") - fd.write(str(port)) - fd.close() - except IOError: - return False - return True - -def getServerAgentCredentials(): - try: - lines = open(Globals.SERVERAGENT_AUTH_FILE).readlines() - except IOError: - return None,None - - userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "AGENT_ID": - userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return userName, password - -def getGatewayAgentCredentials(): - try: - lines = open(Globals.GATEWAYAGENT_AUTH_FILE).readlines() - except IOError: - return None - - #userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - #if k.upper() == "AGENT_ID": - # userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return password - -def getWebAgentCredentials(): - try: - lines = open(Globals.WEBAGENT_AUTH_FILE).readlines() - except IOError: - return None,None - - userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "AGENT_ID": - userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return userName, password - -def daemonize(): - try: - pid = os.fork() - if pid > 0: - # exit first parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - - # do second fork - try: - pid = os.fork() - if pid > 0: - # exit from second parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # redirect standard file descriptors - sys.stdout.flush() - sys.stderr.flush() - si = file("/dev/null", 'r') - so = file("/dev/null", 'a+') - se = file("/dev/null", 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - return True - -def getFreeIpAddress(): - startRange, endRange = getStoragePoolInfo() - if not (startRange and endRange): - return None - - startIpNumber = IP2Number(startRange) - endIpNumber = IP2Number(endRange) - - for ipNumber in range(endIpNumber, startIpNumber, -1): - rv = runCommandFG(["ping", "-qnc", "1", Number2IP(ipNumber)]) - if type(rv) == type(True): - return None - if rv != 0: - return Number2IP(ipNumber) - return None - -def getDhcpServerStatus(): - status = runCommandFG(["sudo", "service", "dnsmasq", " status"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def startDhcpServer(): - status = runCommandFG(["sudo", "service", "dnsmasq", " start"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def stopDhcpServer(): - status = runCommandFG(["sudo", "service", "dnsmasq", " stop"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def getStoragePoolInfo(): - startRange = None - endRange = None - try: - for line in open(Globals.GLUSTER_SERVER_POOL_FILE): - tokens = line.split("=") - if tokens[0] == "STARTRANGE": - startRange = tokens[1].strip() - if tokens[0] == "ENDRANGE": - endRange = tokens[1].strip() - except IOError: - log(syslog.LOG_ERR, "unable to read %s file" % Globals.GLUSTER_SERVER_POOL_FILE) - return startRange, endRange - -def configureDnsmasq(serverIpAddress, dhcpIpAddress): - dnsmasqConfFile = Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf" - serverPortString = "68" - try: - for arg in open("/proc/cmdline").read().strip().split(): - token = arg.split("=") - if token[0] == "dhcp": - serverPortString = token[1] - break - except IOError: - log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") - try: - serverPort = int(serverPortString) - except ValueError: - log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) - serverPort = 68 - - try: - fp = open(dnsmasqConfFile, "w") - fp.write("no-hosts\n") - #fp.write("addn-hosts=%s\n" % Globals.GLUSTER_DNS_ENTRIES) - fp.write("bind-interfaces\n") - fp.write("except-interface=lo\n") - fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) - fp.write("dhcp-lease-max=1\n") - #fp.write("dhcp-option=option:router,%s\n" % serverIp) - #fp.write("dhcp-option=option:ntp-server,%s\n" % serverIp) - fp.write("dhcp-alternate-port=%s\n" % serverPort) - fp.write("server=%s\n" % serverIpAddress) - fp.write("dhcp-script=/usr/sbin/server-info\n") - fp.close() - except IOError: - log(syslog.LOG_ERR, "unable to write dnsmasq configuration %s" % dnsmasqConfFile) - return False - status = runCommandFG(["sudo", "cp", "-f", Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf", Globals.DNSMASQ_CONF_FILE]) - if type(status) == type(True) or 0 != status: - log(syslog.LOG_ERR, "unable to copy dnsmasq configuration to " + Globals.DNSMASQ_CONF_FILE) - return False - return True - -def configureDhcpServer(serverIpAddress, dhcpIpAddress): - return configureDnsmasq(serverIpAddress, dhcpIpAddress) - -def log(priority, message=None): - if type(priority) == type(""): - logPriority = syslog.LOG_INFO - logMessage = priority - else: - logPriority = priority - logMessage = message - if not logMessage: - return - #if Globals.DEBUG: - # sys.stderr.write(logMessage) - else: - syslog.syslog(logPriority, logMessage) - return - - -def stripEmptyLines(content): - ret = "" - for line in content.split("\n"): - if line.strip() != "": - ret += line - return ret - - -def getDeviceFormatStatusFile(device): - return "/var/tmp/format_%s.status" % device.replace('/', '_') - -def getDeviceFormatLockFile(device): - return "/var/lock/format_%s.lock" % device.replace('/', '_') - -def getDeviceFormatOutputFile(device): - return "/var/tmp/format_%s.out" % device.replace('/', '_') diff --git a/src/com.gluster.storage.management.server.scripts/src/VolumeUtils.py b/src/com.gluster.storage.management.server.scripts/src/VolumeUtils.py deleted file mode 100644 index b1031ccc..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/VolumeUtils.py +++ /dev/null @@ -1,612 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import glob -import tempfile -from operator import itemgetter -import Globals -from Protocol import * -from Utils import * -from DiskUtils import * -from ServerUtils import * -import GlusterdUtils as Glusterd - - -def isVolumeExist(volumeName): - volumeDom = XDOM() - return volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)) and \ - Glusterd.isVolumeExist(volumeName) - - -def getVolumeUuid(volumeName): - fileName = "%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName) - volumeDom = XDOM() - if not volumeDom.parseFile(fileName): - log("Failed to parse volume configuration file %s of %s" % (fileName, volumeName)) - return None - return volumeDom.getTextByTagRoute("uuid") - - -def readVolumeSmbConfFile(fileName=Globals.VOLUME_SMBCONF_FILE): - entryList = [] - try: - fp = open(fileName) - for line in fp: - tokens = line.split("#")[0].strip().split(";")[0].strip().split("=") - if len(tokens) != 2: - continue - if tokens[0].strip().upper() == "INCLUDE": - entryList.append(tokens[1].strip()) - fp.close() - except IOError, e: - log("Failed to open file %s: %s" % (fileName, str(e))) - return entryList - - -def writeVolumeSmbConfFile(entryList, fileName=Globals.VOLUME_SMBCONF_FILE): - try: - fp = open(fileName, "w") - for entry in entryList: - fp.write("include = %s\n" % entry) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (fileName, str(e))) - return False - - -def includeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE): - volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) - if not os.path.exists(volumeFile): - return False - entryList = readVolumeSmbConfFile(fileName) - if volumeFile in entryList: - return True - entryList.append(volumeFile) - return writeVolumeSmbConfFile(entryList, fileName) - - -def excludeVolume(volumeName, fileName=Globals.VOLUME_SMBCONF_FILE): - volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) - if not os.path.exists(volumeFile): - return False - entryList = readVolumeSmbConfFile(fileName) - if volumeFile not in entryList: - return True - entryList.remove(volumeFile) - log("entryList = %s" % entryList) - return writeVolumeSmbConfFile(entryList, fileName) - - -def writeVolumeCifsConfiguration(volumeName, userList, adminUser=None): - volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) - try: - fp = open(volumeFile, "w") - fp.write("[%s]\n" % volumeName) - fp.write(" comment = %s volume served by Gluster\n" % volumeName) - fp.write(" path = %s/%s\n" % (Globals.CIFS_EXPORT_DIR, volumeName)) - fp.write(" guest ok = yes\n") - fp.write(" public = yes\n") - fp.write(" writable = yes\n") - if adminUser: - fp.write(" admin users = %s, %s\n" % (adminUser, ", ".join(userList))) - fp.write(" valid users = %s, %s\n" % (adminUser, ", ".join(userList))) - else: - fp.write(" admin users = %s\n" % (", ".join(userList))) - fp.write(" valid users = %s\n" % (", ".join(userList))) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (volumeFile, str(e))) - return False - - -def removeVolumeCifsConfiguration(volumeName): - volumeFile = "%s/%s.smbconf" % (Globals.VOLUME_CONF_DIR, volumeName) - try: - os.remove(volumeFile) - return True - except OSError, e: - log("Failed to remove file %s: %s" % (volumeFile, str(e))) - return False - - -def getVolumeListByPartitionName(partitionName): - volumeConfigFileList = glob.glob(Globals.VOLUME_CONF_DIR + "/*.xml") - if not volumeConfigFileList: - return None - - volumeList = [] - for volumeXmlFile in volumeConfigFileList: - volumeDom = XDOM() - volumeDom.parseFile(volumeXmlFile) - serverTopology = volumeDom.getElementsByTagRoute("volume.topology.group") - serverPartitionFound = False - for topology in serverTopology: - partitionDom = XDOM() - for partition in topology.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - if partitionDom.getTextByTagRoute("name") == partitionName: - serverPartitionFound = True - break - if serverPartitionFound: - volumeList.append(volumeDom.getElementsByTagRoute("volume")[0]) - break - return volumeList - - -def addServerPartitionConfig(inputDom, groupOrder, partitionTag): - if not(inputDom and groupOrder and partitionTag): - return False - groupDom = XDOM() - for group in inputDom.getElementsByTagRoute("topology.group"): - groupDom.setDomObj(group) - order = groupDom.getTextByTagRoute("order") - if order and int(order) == groupOrder: - group.appendChild(partitionTag) - return inputDom - return False - - -def removeServerPartitionConfig(inputDom, partitionName): - if not(inputDom and partitionName): - return False - for group in inputDom.getElementsByTagRoute("topology.group"): - partitionDom = XDOM() - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - if partitionDom.getTextByTagRoute("name") == partitionName: - group.removeChild(partition) - return inputDom - return False - - -def updateServerPartitionConfig(inputDom, partitionName, partitionTag): - if not(inputDom and partitionName and partitionTag): - return False - for group in inputDom.getElementsByTagRoute("topology.group"): - partitionDom = XDOM() - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - if partitionDom.getTextByTagRoute("name") == partitionName: - try: - group.replaceChild(partitionTag, partition) - return inputDom - except AttributeError: - return False - return False - - -def getServerPartitionConfigUuid(serverGroupList, serverPartition): - for group in serverGroupList: - if not group: - continue - partitionDom = XDOM() - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - partitionName = partition.getTextByTagName("name") - if not partitionName: - continue - if partitionName == serverPartition: - return partitionDom.getTextByTagName("uuid") - return False - - -def setServerPartitionConfigProperty(inputDom, partitionName, propertyDict): - if not(inputDom and partitionName and propertyDict): - return False - for group in inputDom.getElementsByTagRoute("topology.group"): - partitionDom = XDOM() - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - if partitionDom.getTextByTagRoute("name") == partitionName: - for part in propertyDict.keys(): - x = partition.getElementsByTagName(part) - if x: - x[0].childNodes[0].nodeValue = propertyDict[part] - return inputDom - return False - - -def getSortedServerPartitionConfigProperty(inputDom): - groupDict = {} - if not inputDom: - return None - groupDom = XDOM() - for group in inputDom.getElementsByTagRoute("topology.group"): - groupDom.setDomObj(group) - groupOrder = groupDom.getTextByTagRoute("order") - if not groupOrder: - return None - groupOrder = int(groupOrder) - if groupOrder < 1: - return None - partitionDom = XDOM() - partitionDict = {} - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - partitionName = partitionDom.getTextByTagRoute("name") - if not partitionName: - return None - partitionOrder = partitionDom.getTextByTagRoute("order") - if not partitionOrder: - return None - partitionUuid = partitionDom.getTextByTagRoute("uuid") - partitionOrder = int(partitionOrder) - if partitionOrder < 1: - return None - partitionDetails = partitionName.split(":") - if not partitionDetails or len(partitionDetails) < 1: - return None - partitionDict[partitionOrder] = { "order":partitionOrder, - "servername":partitionDetails[0], - "name":partitionDetails[1], - "uuid":partitionUuid} - groupDict[groupOrder] = partitionDict - - serverList = [] - groupOrderList = groupDict.keys() - groupOrderList.sort() - for groupOrder in groupOrderList: - partitionOrderList = groupDict[groupOrder].keys() - partitionOrderList.sort() - for partitionOrder in partitionOrderList: - serverList.append(groupDict[groupOrder][partitionOrder]) - - return serverList - - -def getSortedServerPartitionList(serverGroupElements): - serverPartitionDict = {} - groupOrderList = [] - serverList = [] - partitionDom = XDOM() - for group in serverGroupElements: - if not group: - continue - groupOrderE = group.getElementsByTagName("order") - if not (groupOrderE and groupOrderE[0].childNodes): - return None - value = int(XDOM.getText(groupOrderE[0].childNodes)) - if value > 0: - groupOrderList.append(value) - partitionDict = {} - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - - partitionName = partitionDom.getTextByTagRoute("name") - if not partitionName: - return None - partitionOrder = partitionDom.getTextByTagRoute("order") - if not partitionOrder: - return None - partitionUuid = partitionDom.getTextByTagRoute("uuid") - partitionDict[int(partitionOrder)] = [partitionName, partitionUuid] - serverPartitionDict[value] = partitionDict - groupOrderList.sort() - - for groupOrder in groupOrderList: - items = serverPartitionDict[groupOrder].items() - items.sort(key = itemgetter(0)) - serverList = serverList + [ items[i][1] for i in range(0,len(items))] - return serverList - - -def clearExportDirectory(serverList, volumeName, volumeUuid): - thisServerName = getCurrentServerName() - for exportServer in serverList: - serverName, partition = exportServer[0].split(":") - if thisServerName != serverName: - continue - partitionUuid = getUuidByDiskPartition(getDevice(partition)) - if not partitionUuid: - log("unable to find uuid of partition %s" % partition) - return False - volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid) - if os.path.exists(volumeDirName): - ## Removing /data/PARTITION-UUID/VOLUME-UUID/ - ## TODO: Get an option to remove it at this time - if runCommandFG("mv -f %s %s.delete" % (volumeDirName, volumeDirName), root=True) != 0: - return False - if runCommandFG("rm -f %s/%s/volumes/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeName), root=True) != 0: - return False - return True - - -def createExportDirectory(serverList, volumeName, volumeUuid): - thisServerName = getCurrentServerName() - tempVolumeNameFile = getTempFileName() - - try: - fp = open(tempVolumeNameFile, "w") - fp.write("VOLUME_NAME=%s\n" % volumeName) - fp.write("VOLUME_UUID=%s\n" % volumeUuid) - fp.close() - except IOError, e: - log("failed to create temporary file for volume-name: %s" % (volumeName, str(e))) - return False - - for exportServer in serverList: - serverName, partition = exportServer[0].split(":") - if thisServerName != serverName: - continue - partitionUuid = getUuidByDiskPartition(getDevice(partition)) - if not partitionUuid: - log("unable to find uuid of partition %s" % partition) - return False - - volumeDirName = "%s/%s/%s" % (Globals.GLUSTER_LUN_DIR, partitionUuid, volumeUuid) - ## Creating /data/PARTITION-UUID/VOLUME-UUID/ - if runCommandFG("mkdir %s" % volumeDirName, root=True) != 0: - return False - - ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/ - ## Creating /data/PARTITION-UUID/VOLUME-UUID/exports/brick1/ - if runCommandFG("mkdir -p %s/exports/brick1" % volumeDirName, root=True) != 0: - return False - - ## Creating /data/PARTITION-UUID/VOLUME-UUID/log/ - if runCommandFG("mkdir %s/log" % volumeDirName, root=True) != 0: - return False - - ## Creating /data/PARTITION-UUID/VOLUME-UUID/config/ - if runCommandFG("mkdir %s/config" % volumeDirName, root=True) != 0: - return False - - volumeLinkDirName = "%s/%s/volumes" % (Globals.GLUSTER_LUN_DIR, partitionUuid) - if not os.path.exists(volumeLinkDirName): - if runCommandFG("mkdir %s" % volumeLinkDirName, root=True) != 0: - return False - - ## Creating symlink - ## /data/PARTITION-UUID/volumes/VOLUME-NAME -> /data/PARTITION-UUID/VOLUME-UUID/ - command = "ln -fTs %s %s/%s" % (volumeDirName, - volumeLinkDirName, volumeName) - if runCommandFG(command, root=True) != 0: - return False - - if runCommandFG("cp -f %s %s/config/volume-name" % (tempVolumeNameFile, volumeDirName), root=True) != 0: - return False - - try: - os.remove(tempVolumeNameFile) - except OSError, e: - log("Failed to remove file %s: %s" % (tempVolumeNameFile, str(e))) - - return True - - -def getPartitionListByServerName(volumeDom, serverName, serverPartitionList=None): - partitionList = {} - if serverPartitionList: - for partitionName in serverPartitionList: - partitionUuid = getServerDiskPartitionUuid(serverName, partitionName) - if not partitionUuid: - log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName)) - return None - partitionList[partitionName] = partitionUuid - return partitionList - for group in volumeDom.getElementsByTagRoute("topology.group"): - for partitionTag in group.getElementsByTagName("partition"): - nameE = partitionTag.getElementsByTagName("name") - if not nameE: - continue - partition = XDOM.getText(nameE[0].childNodes) - if not partition: - continue - server, partitionName = partition.split(":") - if server != serverName: - continue - partitionUuid = getServerDiskPartitionUuid(serverName, partitionName) - if not partitionUuid: - log(syslog.LOG_ERR, "failed to get disk partition %s uuid of server %s" % (partitionName, serverName)) - return None - partitionList[partitionName] = partitionUuid - return partitionList - - -def isVolumeRunning(volumeName): - return Glusterd.isVolumeRunning(volumeName) - -def addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName): - migrationDom = XDOM() - if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE): - migrationDom.appendTagRoute("volume-migration") - else: - if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): - log("Failed to load volume-migration.xml file") - return None - migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration") - for tagE in migrationList: - dom = XDOM() - dom.setDomObj(tagE) - if dom.getTextByTagRoute("source-partition") == sourcePartition and \ - dom.getTextByTagRoute("destination-partition") == destinationPartition and \ - dom.getTextByTagRoute("volume-name") == volumeName: - return False - migrationTag = migrationDom.getElementsByTagRoute("volume-migration") - if not migrationTag: - return None - partitionTag = migrationDom.createTag("migration") - partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition)) - partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition)) - partitionTag.appendChild(migrationDom.createTag("volume-name", volumeName)) - migrationTag[0].appendChild(partitionTag) - if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE): - log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR) - return False - return True - - -def removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName): - migrationDom = XDOM() - if not os.path.exists(Globals.VOLUME_MIGRATION_LIST_FILE): - return None - if not migrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): - log("Failed to load volume-migration.xml file") - return None - migrationList = migrationDom.getElementsByTagRoute("volume-migration.migration") - for tagE in migrationList: - dom = XDOM() - dom.setDomObj(tagE) - if dom.getTextByTagRoute("source-partition") == sourcePartition and \ - dom.getTextByTagRoute("destination-partition") == destinationPartition and \ - dom.getTextByTagRoute("volume-name") == volumeName: - migrationDom.getElementsByTagRoute("volume-migration")[0].removeChild(tagE) - if not migrationDom.writexml(Globals.VOLUME_MIGRATION_LIST_FILE): - log("Unable to write disk migration details into %s/volume-migration.xml" % Globals.GLUSTER_BASE_DIR) - return False - return True - - -def addPartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None): - migrationDom = XDOM() - if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): - migrationDom.appendTagRoute("partition-migration") - else: - if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): - log("Failed to load migration.xml file") - return None - migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") - for tagE in migrationList: - dom = XDOM() - dom.setDomObj(tagE) - if dom.getTextByTagRoute("source-partition") == sourcePartition: - return False - if dom.getTextByTagRoute("destination-partition") == destinationPartition: - return False - migrationTag = migrationDom.getElementsByTagRoute("partition-migration") - if not migrationTag: - return None - partitionTag = migrationDom.createTag("migration") - partitionTag.appendChild(migrationDom.createTag("source-partition", sourcePartition)) - partitionTag.appendChild(migrationDom.createTag("destination-partition", destinationPartition)) - migrationTag[0].appendChild(partitionTag) - if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE): - log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR) - return False - if volumeList: - for volumeName in volumeList: - addVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName) - return True - - -def removePartitionMigrationDetails(sourcePartition, destinationPartition, volumeList=None): - migrationDom = XDOM() - if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): - return None - if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): - log("Failed to load migration.xml file") - return None - migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") - for tagE in migrationList: - dom = XDOM() - dom.setDomObj(tagE) - if dom.getTextByTagRoute("source-partition") == sourcePartition and \ - dom.getTextByTagRoute("destination-partition") == destinationPartition: - migrationDom.getElementsByTagRoute("partition-migration")[0].removeChild(tagE) - if not migrationDom.writexml(Globals.MIGRATE_PARTITION_LIST_FILE): - log("Unable to write disk migration details into %s/migration.xml" % Globals.GLUSTER_BASE_DIR) - return False - if volumeList: - for volumeName in volumeList: - removeVolumeMigrationDetails(sourcePartition, destinationPartition, volumeName) - return True - - -def isMigrationInProgress(partition): - migrationDom = XDOM() - if not os.path.exists(Globals.MIGRATE_PARTITION_LIST_FILE): - return None - if not migrationDom.parseFile(Globals.MIGRATE_PARTITION_LIST_FILE): - log("Failed to load migration.xml file") - return None - migrationList = migrationDom.getElementsByTagRoute("partition-migration.migration") - for tagE in migrationList: - dom = XDOM() - dom.setDomObj(tagE) - if migrationDom.getTextByTagRoute("source-partition") == partition or \ - migrationDom.getTextByTagRoute("destination-partition") == partition: - return True - return False - - -def getServerDiskPartitionUuid(serverName, partition): - diskConfigDom = XDOM() - if not diskConfigDom.parseFile("%s/%s/disk.xml" % (Globals.SERVER_CONF_DIR, serverName)): - return None - for disk in diskConfigDom.getElementsByTagRoute("disks.disk"): - diskDom = XDOM() - diskDom.setDomObj(disk) - partitionList = diskDom.getElementsByTagRoute("partition") - for tagE in partitionList: - partitionDom = XDOM() - partitionDom.setDomObj(tagE) - if partitionDom.getTextByTagRoute("device") == partition: - return partitionDom.getTextByTagRoute("uuid") - - -def getVolumeServerList(requestDom, requestFlag=True): - if requestFlag: - serverGroupElementList = requestDom.getElementsByTagRoute("command.volume.topology.group") - else: - serverGroupElementList = requestDom.getElementsByTagRoute("volume.topology.group") - if not serverGroupElementList: - return None - serverList = [] - partitionDom = XDOM() - for group in serverGroupElementList: - for partition in group.getElementsByTagName("partition"): - partitionDom.setDomObj(partition) - partitionName = partitionDom.getTextByTagRoute("name") - if not partitionName: - continue - serverPartition = partitionName.split(":") - if not(len(serverPartition) > 1 and serverPartition[1]): - return None - if serverPartition[0] not in serverList: - serverList.append(serverPartition[0]) - return serverList - - -def getVolumeServerListByName(volumeName): - serverList = [] - serverDom = XDOM() - volumeDom = XDOM() - if not os.path.exists("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)): - return False - if not volumeDom.parseFile("%s/%s.xml" % (Globals.VOLUME_CONF_DIR, volumeName)): - return False - return getVolumeServerList(volumeDom, False) - - -def getMigrateVolumeServerPartitionInfo(volumeName): - volumeMigrationDom = XDOM() - if not volumeMigrationDom.parseFile(Globals.VOLUME_MIGRATION_LIST_FILE): - Utils.log("Failed to parse file %s" % Globals.VOLUME_MIGRATION_LIST_FILE) - return None - volumeInfo = {} - dom = XDOM() - for tagE in volumeMigrationDom.getElementsByTagRoute("volume-migration.migration"): - dom.setDomObj(tagE) - if dom.getTextByTagRoute("volume-name") == volumeName: - volumeInfo['Name'] = volumeName - volumeInfo['SourcePartition'] = dom.getTextByTagRoute("source-partition") - volumeInfo['DestinationPartition'] = dom.getTextByTagRoute("destination-partition") - return volumeInfo - return None diff --git a/src/com.gluster.storage.management.server.scripts/src/XmlHandler.py b/src/com.gluster.storage.management.server.scripts/src/XmlHandler.py deleted file mode 100644 index 72164ffb..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/XmlHandler.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import xml -import xml.parsers.expat -import xml.dom.minidom as MDOM -import os -import Globals -import copy -import Utils - -XML_STRING = 0 -XML_FILE = 1 - -class XDOM: - _domObj = None - - def __init__(self): - self._domObj = MDOM.Document() - return - - @classmethod - def getText(self, nodeList): - rc = "" - for node in nodeList: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc - - def parseString(self, requestString): - try: - self._domObj = MDOM.parseString(requestString) - except xml.parsers.expat.ExpatError, e: - Utils.log("XML string parse error: %s" % str(e)) - return False - return True - - def parseFile(self, fileName): - try: - self._domObj = MDOM.parse(fileName) - except IOError, e: - Utils.log("error reading file: %s" % str(e)) - return False - except xml.parsers.expat.ExpatError, e: - Utils.log("XML file %s parse error: %s" % (fileName, str(e))) - return False - return True - - def setDomObj(self, dom): - if dom and type(dom) != type([]): - self._domObj = dom - return True - return False - - def createTag(self, tag, text=None): - if not self._domObj: - return None - if tag == None: - return None - - tagE = self._domObj.createElement(str(tag)) - if text: - tagEText = self._domObj.createTextNode(str(text)) - tagE.appendChild(tagEText) - return tagE - - def addTag(self, tag): - if not self._domObj: - return False - if not tag: - return False - - self._domObj.appendChild(tag) - return True - - def createTagRoute(self, tagRoute, text=None): - if not tagRoute: - return False - - tagList = tagRoute.split(".") - tag = None - previousTag = None - for tagName in tagList[:-1]: - newTag = self.createTag(tagName, None) - if not tag: - tag = newTag - previousTag = newTag - continue - previousTag.appendChild(newTag) - previousTag = newTag - - if previousTag: - previousTag.appendChild(self.createTag(tagList[-1], text)) - else: - tag = self.createTag(tagList[-1], text) - return tag - - def appendTagRoute(self, tagRoute, value=None): - if not self._domObj: - return False - if not tagRoute: - return False - - parentTagE = self._domObj - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def setTextByTagRoute(self, tagRoute, tagValue): - if not self._domObj: - return None - - if not tagRoute: - return None - - tagE = self.getElementsByTagRoute(tagRoute) - if not tagE: - return False - - parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) - if not parentTagE: - return False - - parentTagE[0].childNodes.remove(tagE[0]) - parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) - return True - - def getElementsByTagRoute(self, tagRoute): - if not self._domObj: - return None - - if not tagRoute: - return None - - x = None - for tag in tagRoute.split("."): - if x is None: - x = self._domObj.getElementsByTagName(tag) - continue - if x == []: - break - x = x[0].getElementsByTagName(tag) - return x - - def getTextByTagRoute(self, tagRoute): - if not self._domObj: - return None - - x = self.getElementsByTagRoute(tagRoute) - if x: - return self.getText(x[0].childNodes) - return None - - def getElementsByTagName(self, name): - if not self._domObj: - return None - return self._domObj.getElementsByTagName(name) - - def writexml(self, fileName, indent="", addindent="", newl=""): - if not self._domObj: - return None - try: - fp = open(fileName, "w") - self._domObj.writexml(fp, indent, addindent, newl) - fp.close() - return True - except IOError: - return False - - def toString(self, indent=" ", newl="\n", encoding = None): - if not self._domObj: - return None - return self._domObj.toprettyxml(indent, newl, encoding) - - def toxml(self, encoding = None): - if not self._domObj: - return None - return self._domObj.toxml(encoding) - - def toprettyxml(self, indent=" ", newl="\n", encoding = None): - return self.toString(indent, newl, encoding) - - def createResponseTag(self): - responseTag = self._domObj.createElement("response") - return responseTag -##--end of XDOM - -class RequestXml(XDOM): - def __init__(self, requestString, type=None): - if None == requestString: - XDOM.__init__(self) - return - try: - if None == type: - if os.path.isfile(requestString): - self._domObj = MDOM.parse(requestString) - else: - self._domObj = MDOM.parseString(requestString) - elif XML_FILE == type: - self._domObj = MDOM.parse(requestString) - elif XML_STRING == type: - self._domObj = MDOM.parseString(requestString) - except IOError: - XDOM.__init__(self) - except xml.parsers.expat.ExpatError: - XDOM.__init__(self) - -##--end of RequestXML - - -class ResponseXml(XDOM): - _responseTag = None - def __init__(self): - XDOM.__init__(self) - self._responseTag = self.createResponseTag() - self._domObj.appendChild(self._responseTag) - - @classmethod - def errorResponse(self, message): - if not self.responseTag: - return False - self.appendTagRoute("status.code", "-1"); - self.appendTagRoute("status.message", message) - - def append(self, tagName, tagValue=None): - if not self._responseTag: - return False - tag = self.createTag(tagName, tagValue) - if tag: - self._responseTag.appendChild(tag) - return True - return False - - def appendTag(self, tag): - if not tag: - return False - if not self._responseTag: - return False - self._responseTag.appendChild(tag) - return True - - def appendTagRoute(self, tagRoute, value=None): - if not self._responseTag: - return None - if not tagRoute: - return None - - parentTagE = self._responseTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return None - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return None - return newTagE - - def appendTagRouteOld(self, tagRoute, value=None): - if not self._responseTag: - return False - if not tagRoute: - return False - - parentTagE = self._responseTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True -##--end of ResponseXml - -def test(): - rs = ResponseXml() - rs.appendTagRoute("status.code", "0"); - rs.appendTagRoute("status.message", "SUCCESS") - serverTag = rs.appendTagRoute("server.name", "Server1") - networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None) - networkTag = rs.createTag("networkInterface", None) - networkTag.appendChild(rs.createTag("name", "interface1")) - networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40")) - networkInterfaces.appendChild(networkTag) - networkTag = rs.createTag("networkInterface", None) - networkTag.appendChild(rs.createTag("name", "interface2")) - networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41")) - networkInterfaces.appendChild(networkTag) - print rs.toprettyxml() - -#test() diff --git a/src/com.gluster.storage.management.server.scripts/src/add_user_cifs.py b/src/com.gluster.storage.management.server.scripts/src/add_user_cifs.py deleted file mode 100755 index 7b9650d1..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/add_user_cifs.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils - -def main(): - if len(sys.argv) < 4: - sys.stderr.write("usage: %s UID USERNAME PASSWORD\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - uid = sys.argv[1] - userName = sys.argv[2] - password = sys.argv[3] - - if Utils.runCommand("groupadd -g %s %s" % (uid, userName)) != 0: - Utils.log("failed to add group gid:%s, name:%s\n" % (uid, userName)) - sys.exit(1) - - command = ["useradd", "-c", Globals.VOLUME_USER_DESCRIPTION, "-M", "-d", "/", "-s", "/sbin/nologin", "-u", uid, "-g", uid, userName] - if Utils.runCommand(command) != 0: - Utils.log("failed to add user uid:%s, name:%s\n" % (uid, userName)) - sys.exit(2) - - if Utils.runCommand("smbpasswd -s -a %s" % userName, - input="%s\n%s\n" % (password, password)) != 0: - Utils.log("failed to set smbpassword of user uid:%s, name:%s\n" % (uid, userName)) - sys.exit(3) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/clear_volume_directory.py b/src/com.gluster.storage.management.server.scripts/src/clear_volume_directory.py deleted file mode 100755 index 96677f56..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/clear_volume_directory.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -import syslog -import time -from XmlHandler import ResponseXml -import DiskUtils -import Utils -from optparse import OptionParser - -def clearVolumeDirectory(diskMountPoint, volumeName, todelete): - rs = ResponseXml() - if not DiskUtils.checkDiskMountPoint(diskMountPoint): - Utils.log("failed to find disk mount point %s" % diskMountPoint) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: Mount point does not exists") - return rs.toprettyxml() - - if not os.path.exists(diskMountPoint): - rs.appendTagRoute("status.code", "-2") - rs.appendTagRoute("status.message", "Error: Mount point path does not exists") - return rs.toprettyxml() - - # clear volume directory from the disk - volumeDirectory = "%s/%s" % (diskMountPoint, volumeName) - if not os.path.exists(volumeDirectory): - rs.appendTagRoute("status.code", "-3") - rs.appendTagRoute("status.message", "Error: Volume directory does not exists") - return rs.toprettyxml() - - newVolumeDirectoryName = "%s_%s" % (volumeDirectory, time.time()) - command = ["sudo", "mv", "-f", volumeDirectory, newVolumeDirectoryName] - rv = Utils.runCommandFG(command, stdout=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to rename volume directory %s, %s" % (volumeDirectory, error)) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - - if not todelete: - rv["Status"] = "0" - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - - command = ["sudo", "rm", "-fr", newVolumeDirectoryName] - rv = Utils.runCommandFG(command, stdout=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to clear volume directory %s, %s" % (newVolumeDirectoryName, error)) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - - if not rv["Status"]: - rv["Status"] = "0" - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - -def main(): - parser = OptionParser() - parser.add_option("-d", "--delete", dest="deletedir", action="store_true", default=False, help="force delete") - (options, args) = parser.parse_args() - - if len(args) != 2: - sys.stderr.write("usage: %s [-d/--delete]\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - diskMountPoint = args[0] - volumeName = args[1] - print clearVolumeDirectory(diskMountPoint, volumeName, options.deletedir) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/create_volume_cifs.py b/src/com.gluster.storage.management.server.scripts/src/create_volume_cifs.py deleted file mode 100755 index a81b165b..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/create_volume_cifs.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils -import VolumeUtils - -def main(): - if len(sys.argv) < 3: - sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - userList = sys.argv[2:] - - volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) - try: - os.mkdir(volumeMountDirName) - except OSError, e: - Utils.log("failed creating %s: %s\n" % (volumeMountDirName, str(e))) - sys.exit(1) - - if VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList): - sys.exit(0) - sys.exit(2) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/create_volume_directory.py b/src/com.gluster.storage.management.server.scripts/src/create_volume_directory.py deleted file mode 100755 index 3e633697..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/create_volume_directory.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -from XmlHandler import ResponseXml -import DiskUtils -import Utils - -def createDirectory(disk, volumeName): - # Retrieving disk uuid - diskUuid = DiskUtils.getUuidByDiskPartition(DiskUtils.getDevice(disk)) - - rs = ResponseXml() - if not diskUuid: - Utils.log("failed to find disk:%s uuid" % disk) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: Unable to find disk uuid") - return rs.toprettyxml() - - # Retrieving disk mount point using disk uuid - diskMountPoint = DiskUtils.getMountPointByUuid(diskUuid) - if not os.path.exists(diskMountPoint): - Utils.log("failed to retrieve disk:%s mount point" % disk) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: Failed to retrieve disk details") - return rs.toprettyxml() - - # creating volume directory under disk mount point - volumeDirectory = "%s/%s" % (diskMountPoint, volumeName) - if os.path.exists(volumeDirectory): - Utils.log("Volume directory:%s already exists" % (volumeDirectory)) - rs.appendTagRoute("status.code", "-2") - rs.appendTagRoute("status.message", "Volume directory already exists!") - return rs.toprettyxml() - - if not os.path.exists(volumeDirectory): - command = ["sudo", "mkdir", volumeDirectory] - rv = Utils.runCommandFG(command, stdout=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to create volume directory %s, %s" % (volumeDirectory, error)) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - - if not rv["Status"]: - rv["Status"] = "0" - if rv["Status"] == "0": - message = volumeDirectory - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toprettyxml() - -def main(): - if len(sys.argv) != 3: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - disk = sys.argv[1] - volumeName = sys.argv[2] - print createDirectory(disk, volumeName) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/delete_user_cifs.py b/src/com.gluster.storage.management.server.scripts/src/delete_user_cifs.py deleted file mode 100755 index e5cda957..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/delete_user_cifs.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Utils - -def main(): - if len(sys.argv) < 2: - sys.stderr.write("usage: %s USERNAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - userName = sys.argv[1] - - if Utils.runCommand("userdel %s" % userName) != 0: - Utils.log("failed to remove user name:%s\n" % userName) - sys.exit(1) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/delete_volume_cifs.py b/src/com.gluster.storage.management.server.scripts/src/delete_volume_cifs.py deleted file mode 100755 index fd1febc9..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/delete_volume_cifs.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils -import VolumeUtils - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - - volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) - try: - os.rmdir(volumeMountDirName) - except OSError, e: - Utils.log("failed deleting %s: %s\n" % (volumeMountDirName, str(e))) - sys.exit(1) - - if VolumeUtils.removeVolumeCifsConfiguration(volumeName): - sys.exit(0) - sys.exit(2) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/disable-ssh-password-auth.sh b/src/com.gluster.storage.management.server.scripts/src/disable-ssh-password-auth.sh deleted file mode 100755 index 07ee1a3a..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/disable-ssh-password-auth.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# disable-ssh-password-auth.sh -# Script for disabling SSH password authentication. This is used by the -# management gateway after installing the public key, so that the gluster -# node can be accessed (using ssh) only from the management gateway. -#----------------------------------------------------------------------------- - -CONFIG_FILE="/etc/ssh/sshd_config" -TIMESTAMP=`date +%d%m%Y%H%M%S` -BACKUP_FILE="${CONFIG_FILE}_${TIMESTAMP}" -TEMP_FILE="/tmp/new_sshd_config_${TIMESTAMP}" - -# Modify config file to disable password authentication, redirect to a temp file -# TODO: disable only if enabled! -sed "s/^PasswordAuthentication yes$/PasswordAuthentication no/g" ${CONFIG_FILE} > ${TEMP_FILE} - -# Secure the file by changing permissions (600) -chmod 600 ${TEMP_FILE} - -# Take backup of config file -cp ${CONFIG_FILE} ${BACKUP_FILE} - -# Overwrite config file with the modified one -mv ${TEMP_FILE} ${CONFIG_FILE} - -# Re-start ssh daemon -/etc/init.d/sshd restart - diff --git a/src/com.gluster.storage.management.server.scripts/src/format_device.py b/src/com.gluster.storage.management.server.scripts/src/format_device.py deleted file mode 100755 index 3bc70532..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/format_device.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import sys -import Globals -import Utils -import DiskUtils -from optparse import OptionParser - - -def main(): - if Utils.runCommand("wget -q -O /dev/null %s" % Globals.AWS_WEB_SERVICE_URL) == 0: - sys.stderr.write("format device unsupported") - sys.exit(1) - - parser = OptionParser() - parser.add_option("-t", "--type", action="store", type="string", dest="fstype") - (options, args) = parser.parse_args() - - if len(args) != 1: - sys.stderr.write("usage: %s [-t FSTYPE] DEVICE_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - device = DiskUtils.getDevice(args[0]) - deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) - deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) - deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) - - if DiskUtils.isDataDiskPartitionFormatted(device): - sys.stderr.write("Device already formatted\n") - sys.exit(2) - - if os.path.exists(deviceFormatStatusFile): - Utils.log("format status file %s exists" % deviceFormatStatusFile) - try: - fp = open(deviceFormatStatusFile) - line = fp.read() - fp.close() - if line.strip().upper() == "COMPLETED": - sys.stderr.write("Device already formatted\n") - sys.exit(3) - else: - sys.stderr.write("Device format already running\n") - sys.exit(4) - except IOError, e: - Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e))) - sys.stderr.write("%s\n" % str(e)) - sys.exit(-2) - - if os.path.exists(deviceFormatLockFile): - Utils.log("lock file %s exists" % deviceFormatLockFile) - sys.stderr.write("Device format already running\n") - sys.exit(5) - - if options.fstype: - command = ["gluster_provision_block_wrapper.py", "-t", "%s" % (options.fstype), "%s" % (device)] - else: - command = ["gluster_provision_block_wrapper.py", "%s" % (device)] - - try: - pid = os.fork() - except OSError, e: - Utils.log("failed to fork a child process: %s" % str(e)) - sys.exit(6) - if pid == 0: - os.execv("/usr/sbin/gluster_provision_block_wrapper.py", command) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_brick_status.py b/src/com.gluster.storage.management.server.scripts/src/get_brick_status.py deleted file mode 100755 index cf84080b..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_brick_status.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Console. -# - -import os -import sys -import Utils - -def main(): - if len(sys.argv) != 3: - sys.stderr.write("usage: %s VOLUME_NAME BRICK_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - brickName = sys.argv[2] - pidFile = "/etc/glusterd/vols/%s/run/%s.pid" % (volumeName, brickName.replace(":", "").replace("/", "-")) - - if not os.path.exists(pidFile): - print "OFFLINE" - else: - try: - fp = open(pidFile) - pidString = fp.readline() - fp.close() - os.getpgid(int(pidString)) - print "ONLINE" - except IOError, e: - Utils.log("failed to open file %s: %s" % (pidFile, str(e))) - print "UNKNOWN" - except ValueError, e: - Utils.log("invalid pid %s in file %s: %s" % (pidString, pidFile, str(e))) - print "UNKNOWN" - except OSError, e: - #Utils.log("failed to get process detail of pid %s: %s" % (pidString, str(e))) - print "OFFLINE" - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_disk_mount_point.py b/src/com.gluster.storage.management.server.scripts/src/get_disk_mount_point.py deleted file mode 100755 index 2f4a39c3..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_disk_mount_point.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import Utils -from DiskUtils import * -from XmlHandler import ResponseXml - - -def getmountpoint(path): - if not path: - Utils.log("Not a valid path:%s" % path) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: given path name is empty") - return rs.toprettyxml() - - rs = ResponseXml() - mountPoint = None - - for line in readFsTab(): - if path.startswith(line['MountPoint']): - if not mountPoint: - mountPoint = line['MountPoint'] - if len(line['MountPoint']) > len(mountPoint): - mountPoint = line['MountPoint'] - - if "/" == mountPoint or not mountPoint: - Utils.log("failed to find mount point of the given path:%s" % path) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: Unable to find disk mount point") - return rs.toprettyxml() - - rs.appendTagRoute("status.code", "0") - rs.appendTagRoute("status.message", mountPoint) - return rs.toprettyxml() - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - path = sys.argv[1] - print getmountpoint(path) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_disk_name_by_path.py b/src/com.gluster.storage.management.server.scripts/src/get_disk_name_by_path.py deleted file mode 100755 index 08e80b7e..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_disk_name_by_path.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import Utils -from DiskUtils import * -from XmlHandler import ResponseXml - - -def getmountpoint(path): - if not path: - Utils.log("Not a valid path:%s" % path) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: given path name is empty") - return rs.toprettyxml() - - rs = ResponseXml() - mountPoint = None - fsTabEntry = None - for line in readFsTab(): - if path.startswith(line['MountPoint']): - if not mountPoint: - mountPoint = line['MountPoint'] - fsTabEntry = line - if len(line['MountPoint']) > len(mountPoint): - mountPoint = line['MountPoint'] - fsTabEntry = line - - if "/" == mountPoint or not mountPoint: - Utils.log("failed to find mount point of the given path:%s" % path) - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "Error: Unable to find disk mount point") - return rs.toprettyxml() - - rs.appendTagRoute("status.code", "0") - if fsTabEntry["Device"].startswith("UUID="): - rs.appendTagRoute("status.message", getDiskPartitionByUuid(fsTabEntry["Device"].split("UUID=")[-1])) - else: - rs.appendTagRoute("status.message", "Unable to find disk name") - return rs.toprettyxml() - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - path = sys.argv[1] - print getmountpoint(path) - sys.exit(0) - -if __name__ == "__main__": - main() - diff --git a/src/com.gluster.storage.management.server.scripts/src/get_file.py b/src/com.gluster.storage.management.server.scripts/src/get_file.py deleted file mode 100755 index 61c33eba..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_file.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) 2009,2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import Globals -import Utils -from VolumeUtils import * -from XmlHandler import ResponseXml - - -def enumLogType(logCode): - if "M" == logCode.upper(): - return "EMERGENCY" - elif "A" == logCode.upper(): - return "ALERT" - elif "C" == logCode.upper(): - return "CRITICAL" - elif "E" == logCode.upper(): - return "ERROR" - elif "W" == logCode.upper(): - return "WARNING" - elif "N" == logCode.upper(): - return "NOTICE" - elif "I" == logCode.upper(): - return "INFO" - elif "D" == logCode.upper(): - return "DEBUG" - elif "T" == logCode.upper(): - return "TRACE" - else: - return "UNKNOWN" -##--end of enumLogType() - - -def addLog(responseDom, logMessageTag, loginfo): - logTag = responseDom.createTag("log", None) - logTag.appendChild(responseDom.createTag("date", loginfo[0])) - logTag.appendChild(responseDom.createTag("time", loginfo[1])) - logTag.appendChild(responseDom.createTag("type", enumLogType(loginfo[2]))) - logTag.appendChild(responseDom.createTag("message", loginfo[3])) - logMessageTag.appendChild(logTag) - return True -##--end of addLog() - - -def logSplit(log): - loginfo = log.strip().split(None, 3) - loginfo[0] = loginfo[0][1:] #-- Remove '[' - loginfo[1] = loginfo[1][0:-1] #-- Remove ']' - return loginfo -##--end of logSplit() - - -def getVolumeLog(volumeName, tailCount): - rs = ResponseXml() - if not volumeName: - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "No volume name given") - return rs.toprettyxml() - - if not tailCount: - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "No tail count given") - return rs.toprettyxml() - - thisServerName = getCurrentServerName() - if not thisServerName: - rs.appendTagRoute("status.code", "-2") - rs.appendTagRoute("status.message", "Failed to get current server name") - return rs.toprettyxml() - - volumeDom = XDOM() - partitionList = getPartitionListByServerName(volumeDom, thisServerName) - if not partitionList: - rs.appendTagRoute("status.code", "-3") - rs.appendTagRoute("status.message", "Failed to get server partition details") - return rs.toprettyxml() - - pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' - logMessagesTag = rs.createTag("response.logMessages") - for partitionName in partitionList: - logMessageTag = rs.createTag("logMessage") - logMessageTag.appendChild("disk", "%s:%s" % (thisServerName, partitionName)) - - logDirectory = "%s/%s/%s/log" % (Globals.GLUSTER_LUN_DIR, partitionList[partitionName], volumeUuid) - logFileName = "%s/%s-%s-%s-exports-brick1.log" % (logDirectory, - Globals.GLUSTER_LUN_DIR[1:], - partitionList[partitionName], - volumeUuid) - if not os.path.exists(logFileName): - Utils.log("volume log file not found %s" % logFileName) - continue - fp = open(logFileName) - lines = [line for line in fp if re.match(pattern, line)] - fp.close() - i = len(lines) - int(tailCount) - if i < 0: - i = 0 - for log in lines[i:]: - loginfo = logSplit(log) - addLog(rs, logMessageTag, loginfo) - logMessagesTag.appendChild(logMessageTag) - return rs.toprettyxml() -##--end of getVolumeLog() - -def main(): - if len(sys.argv) != 3: - print >> sys.stderr, "usage: %s " % sys.argv[0] - sys.exit(-1) - - volumeName = sys.argv[1] - tailCount = sys.argv[2] - print getVolumeLog(volumeName, tailCount) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_format_device_status.py b/src/com.gluster.storage.management.server.scripts/src/get_format_device_status.py deleted file mode 100755 index 57fc0455..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_format_device_status.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009,2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import sys -import time -import Utils -import DiskUtils -from XmlHandler import ResponseXml - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s DEVICE_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - device = DiskUtils.getDevice(sys.argv[1]) - - deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) - deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) - deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) - - time.sleep(1) - if not os.path.exists(deviceFormatLockFile): - if not os.path.exists(deviceFormatStatusFile): - sys.stderr.write("Device format not initiated\n") - sys.exit(1) - - if os.path.exists(deviceFormatStatusFile): - try: - fp = open(deviceFormatStatusFile) - line = fp.read() - fp.close() - line = line.strip() - - Utils.removeFile(deviceFormatOutputFile) - Utils.removeFile(deviceFormatStatusFile) - - responseDom = ResponseXml() - responseDom.appendTagRoute("device", sys.argv[1]) - responseDom.appendTagRoute("completedBlocks", "0") - responseDom.appendTagRoute("totalBlocks", "0") - responseDom.appendTagRoute("message", line) - if line.upper() == "COMPLETED": - responseDom.appendTagRoute("formatStatus", "COMPLETED") - else: - responseDom.appendTagRoute("formatStatus", "NOT_RUNNING") - print responseDom.toxml() - sys.exit(0) - except IOError, e: - Utils.log("failed to read format status file %s: %s" % (deviceFormatStatusFile, str(e))) - sys.stderr.write("%s\n" % str(e)) - sys.exit(-2) - - if not os.path.exists(deviceFormatOutputFile): - responseDom = ResponseXml() - responseDom.appendTagRoute("device", sys.argv[1]) - responseDom.appendTagRoute("completedBlocks", "0") - responseDom.appendTagRoute("totalBlocks", "0") - responseDom.appendTagRoute("message", None) - responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") - print responseDom.toxml() - sys.exit(0) - - try: - fp = open(deviceFormatOutputFile) - content = fp.read() - fp.close() - except IOError, e: - Utils.log("failed to read format output file %s: %s" % (deviceFormatOutputFile, str(e))) - responseDom = ResponseXml() - responseDom.appendTagRoute("device", sys.argv[1]) - responseDom.appendTagRoute("completedBlocks", "0") - responseDom.appendTagRoute("totalBlocks", "0") - responseDom.appendTagRoute("message", None) - responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") - print responseDom.toxml() - sys.exit(0) - - lines = [line for line in content - if "Writing inode tables" in line] - if not lines: - responseDom = ResponseXml() - responseDom.appendTagRoute("device", sys.argv[1]) - responseDom.appendTagRoute("completedBlocks", "0") - responseDom.appendTagRoute("totalBlocks", "0") - if content: - responseDom.appendTagRoute("message", content[-1]) - else: - responseDom.appendTagRoute("message") - responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") - print responseDom.toxml() - sys.exit(0) - - tokens = [token for token in lines[-1].split("\x08") if token] - if "done" in tokens[-1]: - values = tokens[-2].split(':')[-1].strip().split('/') - else: - values = tokens[-1].split(':')[-1].strip().split('/') - - responseDom.appendTagRoute("device", sys.argv[1]) - responseDom.appendTagRoute("completedBlocks", values[0]) - responseDom.appendTagRoute("totalBlocks", values[1]) - responseDom.appendTagRoute("message", lines[-1]) - responseDom.appendTagRoute("formatStatus", "IN_PROGRESS") - print responseDom.toxml() - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_rrd_cpu_details.py b/src/com.gluster.storage.management.server.scripts/src/get_rrd_cpu_details.py deleted file mode 100755 index 546aec31..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_rrd_cpu_details.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -from XmlHandler import ResponseXml -import Utils - -def getCpuData(period): - cpuRrdFile = "/var/lib/rrd/cpu.rrd" - rs = ResponseXml() - command = "rrdtool xport --start -%s \ - DEF:cpuuser=%s:user:AVERAGE \ - DEF:cpusystem=%s:system:AVERAGE \ - CDEF:total=cpuuser,cpusystem,+ \ - XPORT:cpuuser:user \ - XPORT:cpusystem:system \ - XPORT:total:total" % (period, cpuRrdFile, cpuRrdFile) - - rv = Utils.runCommand(command, output=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to create RRD file for cpu usages %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return rv["Stdout"] - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - period = sys.argv[1] - print getCpuData(period) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_rrd_memory_details.py b/src/com.gluster.storage.management.server.scripts/src/get_rrd_memory_details.py deleted file mode 100755 index f7c3031b..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_rrd_memory_details.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -# Input command: get_rrd_memory_details.py 1hour -# OUTPUT as bellow: -# -# -# -# -# 1310455500 -# 300 -# 1310459100 -# 13 -# 5 -# -# memoryUsed -# memoryFree -# memoryCache -# memoryBuffer -# totalMemory -# -# -# -# 13104555001.9181091707e+061.5819754974e+061.2528146351e+061.2528146351e+063.5000846681e+06 -# --- -# --- -# -# - -import os -import sys -import syslog -from XmlHandler import ResponseXml -import Utils - -def getMemData(period): - memRrdFile = "/var/lib/rrd/mem.rrd" - rs = ResponseXml() - command = "rrdtool xport --start -%s \ - DEF:free=%s:memfree:AVERAGE \ - DEF:used=%s:memused:AVERAGE \ - DEF:cache=%s:memcache:AVERAGE \ - DEF:buffer=%s:membuffer:AVERAGE \ - CDEF:total1=used,free,+ \ - CDEF:used1=used,buffer,cache,-,- \ - CDEF:total=total1,used1,+ \ - XPORT:used:memoryUsed \ - XPORT:free:memoryFree \ - XPORT:cache:memoryCache \ - XPORT:buffer:memoryBuffer \ - XPORT:total:totalMemory" % (period, memRrdFile, memRrdFile, memRrdFile, memRrdFile) - - rv = Utils.runCommand(command, output=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to create RRD file for memory usages %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return rv["Stdout"] - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - period = sys.argv[1] - print getMemData(period) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_rrd_net_details.py b/src/com.gluster.storage.management.server.scripts/src/get_rrd_net_details.py deleted file mode 100755 index 6a31cde8..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_rrd_net_details.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -from XmlHandler import ResponseXml -import Utils - -def main(): - if len(sys.argv) != 3: - sys.stderr.write("usage: %s \n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - device = sys.argv[1] - period = sys.argv[2] - - rs = ResponseXml() - command = "rrdtool xport --start -%s \ - DEF:received=/var/lib/rrd/network-%s.rrd:received:AVERAGE \ - DEF:transmitted=/var/lib/rrd/network-%s.rrd:transmitted:AVERAGE \ - CDEF:total=received,transmitted,+ \ - XPORT:received:received \ - XPORT:transmitted:transmitted \ - XPORT:total:total" % (period, device, device) - rv = Utils.runCommand(command, output=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to get RRD information of device %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - print rs.toxml() - print rv["Stdout"] - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_server_details.py b/src/com.gluster.storage.management.server.scripts/src/get_server_details.py deleted file mode 100755 index 9c3da741..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_server_details.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import socket -import re -import Utils -import DiskUtils -from NetworkUtils import * -from Disk import * -from XmlHandler import ResponseXml -from optparse import OptionParser - - -def getServerDetails(listall): - serverName = socket.gethostname() - meminfo = getMeminfo() - cpu = getCpuUsageAvg() - nameServerList, domain, searchDomain = readResolvConfFile() - if not domain: - domain = [None] - - responseDom = ResponseXml() - serverTag = responseDom.appendTagRoute("server") - serverTag.appendChild(responseDom.createTag("name", serverName)) - serverTag.appendChild(responseDom.createTag("domainname", domain[0])) - if Utils.runCommand("pidof glusterd") == 0: - serverTag.appendChild(responseDom.createTag("status", "ONLINE")) - else: - serverTag.appendChild(responseDom.createTag("status", "OFFLINE")) - serverTag.appendChild(responseDom.createTag("cpuUsage", str(cpu))) - serverTag.appendChild(responseDom.createTag("totalMemory", str(convertKbToMb(meminfo['MemTotal'])))) - serverTag.appendChild(responseDom.createTag("memoryInUse", str(convertKbToMb(meminfo['MemUsed'])))) - serverTag.appendChild(responseDom.createTag("uuid", None)) - - for dns in nameServerList: - serverTag.appendChild(responseDom.createTag("dns%s" % str(nameServerList.index(dns) +1) , dns)) - - #TODO: probe and retrieve timezone, ntp-server details and update the tags - - deviceList = {} - interfaces = responseDom.createTag("networkInterfaces", None) - for device in getNetDeviceList(): - if device["model"] in ['LOCAL', 'IPV6-IN-IPV4']: - continue - deviceList[device["device"]] = device - try: - macAddress = open("/sys/class/net/%s/address" % device["device"]).read().strip() - except IOError: - continue - interfaceTag = responseDom.createTag("networkInterface", None) - interfaceTag.appendChild(responseDom.createTag("name", device["device"])) - interfaceTag.appendChild(responseDom.createTag("hwAddr",macAddress)) - interfaceTag.appendChild(responseDom.createTag("speed", device["speed"])) - interfaceTag.appendChild(responseDom.createTag("model", device["model"])) - if deviceList[device["device"]]: - if deviceList[device["device"]]["onboot"]: - interfaceTag.appendChild(responseDom.createTag("onboot", "yes")) - else: - interfaceTag.appendChild(responseDom.createTag("onBoot", "no")) - interfaceTag.appendChild(responseDom.createTag("bootProto", deviceList[device["device"]]["bootproto"])) - interfaceTag.appendChild(responseDom.createTag("ipAddress", deviceList[device["device"]]["ipaddr"])) - interfaceTag.appendChild(responseDom.createTag("netMask", deviceList[device["device"]]["netmask"])) - interfaceTag.appendChild(responseDom.createTag("defaultGateway", deviceList[device["device"]]["gateway"])) - if deviceList[device["device"]]["mode"]: - interfaceTag.appendChild(responseDom.createTag("mode", deviceList[device["device"]]["mode"])) - if deviceList[device["device"]]["master"]: - interfaceTag.appendChild(responseDom.createTag("bonding", "yes")) - spliter = re.compile(r'[\D]') - interfaceTag.appendChild(responseDom.createTag("bondid", spliter.split(device["master"])[-1])) - else: - interfaceTag.appendChild(responseDom.createTag("onBoot", "no")) - interfaceTag.appendChild(responseDom.createTag("bootProto", "none")) - interfaces.appendChild(interfaceTag) - serverTag.appendChild(interfaces) - - responseDom.appendTag(serverTag) - serverTag.appendChild(responseDom.createTag("numOfCPUs", int(os.sysconf('SC_NPROCESSORS_ONLN')))) - - diskDom = DiskUtils.getDiskDom() - if not diskDom: - sys.stderr.write("No disk found!") - Utils.log("Failed to get disk details") - sys.exit(1) - - serverTag.appendChild(diskDom.getElementsByTagRoute("disks")[0]) - return serverTag - -def main(): - parser = OptionParser() - parser.add_option("-N", "--only-data-disks", - action="store_false", dest="listall", default=True, - help="List only data disks") - - (options, args) = parser.parse_args() - responseXml = getServerDetails(options.listall) - if responseXml: - print responseXml.toxml() - - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_server_status.py b/src/com.gluster.storage.management.server.scripts/src/get_server_status.py deleted file mode 100755 index a57428b6..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_server_status.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Console. -# - -import os -import sys -import Utils - -def main(): - if len(sys.argv) != 1: - sys.stderr.write("usage: %s\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - if Utils.runCommand("pidof glusterd") == 0: - print "ONLINE" - else: - print "OFFLINE" - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_volume_brick_log.py b/src/com.gluster.storage.management.server.scripts/src/get_volume_brick_log.py deleted file mode 100755 index fd7361da..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_volume_brick_log.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009,2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import re -import os -import sys -from XmlHandler import XDOM - -def enumLogType(logCode): - if "M" == logCode.upper(): - return "EMERGENCY" - elif "A" == logCode.upper(): - return "ALERT" - elif "C" == logCode.upper(): - return "CRITICAL" - elif "E" == logCode.upper(): - return "ERROR" - elif "W" == logCode.upper(): - return "WARNING" - elif "N" == logCode.upper(): - return "NOTICE" - elif "I" == logCode.upper(): - return "INFO" - elif "D" == logCode.upper(): - return "DEBUG" - elif "T" == logCode.upper(): - return "TRACE" - else: - return "UNKNOWN" -##--end of enumLogType() - -def addLog(responseDom, logMessagesTag, loginfo): - logMessageTag = responseDom.createTag("logMessage") - logMessageTag.appendChild(responseDom.createTag("timestamp", loginfo[0] + " " + loginfo[1])) - logMessageTag.appendChild(responseDom.createTag("severity", enumLogType(loginfo[2]))) - logMessageTag.appendChild(responseDom.createTag("message", loginfo[3])) - logMessagesTag.appendChild(logMessageTag); - return True -##--end of addLog() - -def logSplit(log): - loginfo = log.strip().split(None, 3) - loginfo[0] = loginfo[0][1:] #-- Remove '[' - loginfo[1] = loginfo[1][0:-1] #-- Remove ']' - return loginfo -##--end of logSplit() - -def getVolumeLog(logFilePath, tailCount): - rs = XDOM() - if not logFilePath: - print >> sys.stderr, "No log file path given" - sys.exit(-1); - - if not tailCount: - print >> sys.stderr, "No tail count given" - sys.exit(-1); - - pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' - if not os.path.exists(logFilePath): - print >> sys.stderr, "volume log file [%s] not found!" % logFilePath - sys.exit(-1); - - fp = open(logFilePath) - lines = [line for line in fp if re.match(pattern, line)] - fp.close() - i = len(lines) - int(tailCount) - if i < 0: - i = 0 - logMessagesTag = rs.createTag("logMessages") - rs.addTag(logMessagesTag) - for log in lines[i:]: - loginfo = logSplit(log) - addLog(rs, logMessagesTag, loginfo) - return rs.toxml() -##--end of getVolumeLog() - -def main(): - if len(sys.argv) != 3: - print >> sys.stderr, "usage: %s " % sys.argv[0] - sys.exit(-1) - - logFilePath = sys.argv[1] - tailCount = sys.argv[2] - print getVolumeLog(logFilePath, tailCount) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/get_volume_log.py b/src/com.gluster.storage.management.server.scripts/src/get_volume_log.py deleted file mode 100755 index b906c002..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/get_volume_log.py +++ /dev/null @@ -1,131 +0,0 @@ -# Copyright (C) 2009,2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import Globals -import syslog -import Utils -from VolumeUtils import * -from XmlHandler import ResponseXml - - -def enumLogType(logCode): - if "M" == logCode.upper(): - return "EMERGENCY" - elif "A" == logCode.upper(): - return "ALERT" - elif "C" == logCode.upper(): - return "CRITICAL" - elif "E" == logCode.upper(): - return "ERROR" - elif "W" == logCode.upper(): - return "WARNING" - elif "N" == logCode.upper(): - return "NOTICE" - elif "I" == logCode.upper(): - return "INFO" - elif "D" == logCode.upper(): - return "DEBUG" - elif "T" == logCode.upper(): - return "TRACE" - else: - return "UNKNOWN" -##--end of enumLogType() - - -def addLog(responseDom, logMessageTag, loginfo): - logTag = responseDom.createTag("log", None) - logTag.appendChild(responseDom.createTag("date", loginfo[0])) - logTag.appendChild(responseDom.createTag("time", loginfo[1])) - logTag.appendChild(responseDom.createTag("type", enumLogType(loginfo[2]))) - logTag.appendChild(responseDom.createTag("message", loginfo[3])) - logMessageTag.appendChild(logTag) - return True -##--end of addLog() - - -def logSplit(log): - loginfo = log.strip().split(None, 3) - loginfo[0] = loginfo[0][1:] #-- Remove '[' - loginfo[1] = loginfo[1][0:-1] #-- Remove ']' - return loginfo -##--end of logSplit() - - -def getVolumeLog(volumeName, tailCount): - rs = ResponseXml() - if not volumeName: - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "No volume name given") - return rs.toprettyxml() - - if not tailCount: - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "No tail count given") - return rs.toprettyxml() - - thisServerName = getCurrentServerName() - if not thisServerName: - rs.appendTagRoute("status.code", "-2") - rs.appendTagRoute("status.message", "Failed to get current server name") - return rs.toprettyxml() - - volumeDom = XDOM() - partitionList = getPartitionListByServerName(volumeDom, thisServerName) - if not partitionList: - rs.appendTagRoute("status.code", "-3") - rs.appendTagRoute("status.message", "Failed to get server partition details") - return rs.toprettyxml() - - pattern = '\[\d{4}-\d{2}-\d{2}\s{1}\d{2}:\d{2}:\d{2}.\d+\]\s{1}([MACEWNIDT]){1}\s+' - logMessagesTag = rs.createTag("response.logMessages") - for partitionName in partitionList: - logMessageTag = rs.createTag("logMessage") - logMessageTag.appendChild("disk", "%s:%s" % (thisServerName, partitionName)) - - logDirectory = "%s/%s/%s/log" % (Globals.GLUSTER_LUN_DIR, partitionList[partitionName], volumeUuid) - logFileName = "%s/%s-%s-%s-exports-brick1.log" % (logDirectory, - Globals.GLUSTER_LUN_DIR[1:], - partitionList[partitionName], - volumeUuid) - if not os.path.exists(logFileName): - Utils.log("volume log file not found %s" % logFileName) - continue - fp = open(logFileName) - lines = [line for line in fp if re.match(pattern, line)] - fp.close() - i = len(lines) - int(tailCount) - if i < 0: - i = 0 - for log in lines[i:]: - loginfo = logSplit(log) - addLog(rs, logMessageTag, loginfo) - logMessagesTag.appendChild(logMessageTag) - return rs.toprettyxml() -##--end of getVolumeLog() - -def main(): - if len(sys.argv) != 3: - print >> sys.stderr, "usage: %s " % sys.argv[0] - sys.exit(-1) - - volumeName = sys.argv[1] - tailCount = sys.argv[2] - print getVolumeLog(volumeName, tailCount) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/gluster_provision_block_wrapper.py b/src/com.gluster.storage.management.server.scripts/src/gluster_provision_block_wrapper.py deleted file mode 100755 index a3b2776d..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/gluster_provision_block_wrapper.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import sys -import subprocess -import Utils -import DiskUtils -from optparse import OptionParser - -def writeStatus(deviceFormatStatusFile, message): - try: - fp = open(deviceFormatStatusFile, "w") - fp.write(message) - fp.close() - except IOError, e: - Utils.log("Failed to update log file %s: %s" % (deviceFormatStatusFile, str(e))) - return False - return True - - -def main(): - parser = OptionParser() - parser.add_option("-t", "--type", action="store", type="string", dest="fstype") - (options, args) = parser.parse_args() - - if len(args) != 1: - sys.stderr.write("usage: %s [-t FSTYPE] DEVICE" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - device = args[0] - deviceFormatLockFile = Utils.getDeviceFormatLockFile(device) - deviceFormatStatusFile = Utils.getDeviceFormatStatusFile(device) - deviceFormatOutputFile = Utils.getDeviceFormatOutputFile(device) - - if os.path.exists(deviceFormatStatusFile): - Utils.log("device format status file %s exists" % deviceFormatStatusFile) - sys.exit(1) - - if os.path.exists(deviceFormatLockFile): - Utils.log("device format lock file %s exists" % deviceFormatLockFile) - sys.exit(2) - - try: - fp = open(deviceFormatLockFile, "w") - fp.close() - except OSError, e: - Utils.log("failed to create lock file %s: %s" % (deviceFormatLockFile, str(e))) - writeStatus(deviceFormatStatusFile, "Lock file creation failed\n") - sys.exit(3) - - try: - fptr = open(deviceFormatOutputFile, 'w') - except IOError, e: - Utils.log("failed to create output file %s" % deviceFormatOutputFile) - writeStatus(deviceFormatStatusFile, "Output file creation failed\n") - Utils.removeFile(deviceFormatLockFile) - sys.exit(4) - - if options.fstype: - command = "gluster-provision-block -t %s %s" % (options.fstype, device) - else: - command = "gluster-provision-block %s" % (device) - - process = Utils.runCommandBG(command, - stdinFileObj=subprocess.PIPE, - stdoutFileObj=fptr, - stderrFileObj=subprocess.PIPE) - if process: - status = process.wait() - else: - Utils.removeFile(deviceFormatOutputFile) - Utils.removeFile(deviceFormatLockFile) - writeStatus(deviceFormatStatusFile, "Device format failed\n") - sys.exit(5) - - if status != 0: - Utils.removeFile(deviceFormatOutputFile) - Utils.removeFile(deviceFormatLockFile) - writeStatus(deviceFormatStatusFile, "Device format failed\n") - sys.exit(6) - - if Utils.runCommand("/sbin/udevtrigger") != 0: - Utils.log("failed running /sbin/udevtrigger") - - if Utils.runCommand("/usr/bin/lshal") != 0: - Utils.log("failed running /usr/bin/lshal") - writeStatus(deviceFormatStatusFile, "Completed\n") - Utils.removeFile(deviceFormatOutputFile) - Utils.removeFile(deviceFormatLockFile) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/modify_volume_cifs.py b/src/com.gluster.storage.management.server.scripts/src/modify_volume_cifs.py deleted file mode 100755 index f6bacfc4..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/modify_volume_cifs.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Utils -import VolumeUtils - -def main(): - if len(sys.argv) <= 2: - sys.stderr.write("usage: %s VOLUME_NAME USER1 USER2 ...\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - userList = sys.argv[2:] - - if not VolumeUtils.writeVolumeCifsConfiguration(volumeName, userList): - sys.exit(1) - if Utils.runCommand("service smb reload") != 0: - Utils.log("Failed to reload smb service") - sys.exit(2) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/multicast_response.py b/src/com.gluster.storage.management.server.scripts/src/multicast_response.py deleted file mode 100644 index 18cf89ae..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/multicast_response.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import os -import string -import time -import Utils -import socket -import struct -import Globals -from XmlHandler import * - -def isInPeer(): - command = "gluster peer status" - status = Utils.runCommand(command, output=True, root=True) - if status["Status"] == 0: - if status["Stdout"].strip().upper() != "NO PEERS PRESENT": - return True - return False - Utils.log("command [%s] failed with [%d:%s]" % (command, status["Status"], os.strerror(status["Status"]))) - return False - -def response(multiCastGroup, port): - # waiting for the request! - socketRequest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketRequest.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - socketRequest.bind(('', port)) - mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) - socketRequest.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - - socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) - - #TODO: Remove infinite loop and make this as a deamon (service) - while True: - request = socketRequest.recvfrom(1024) - if not request: - continue - dom = XDOM() - dom.parseString(request[0]) - if not dom: - continue - if not dom.getTextByTagRoute("request.name"): - continue - requesttime = dom.getTextByTagRoute("request.time") - if not requesttime: - continue - if isInPeer(): - time.sleep(5) - continue - socketSend.sendto("%s" % (socket.gethostname(), requesttime), - (multiCastGroup, port)) - request = None - -def main(): - response(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/rrd_cpu.pl b/src/com.gluster.storage.management.server.scripts/src/rrd_cpu.pl deleted file mode 100755 index 7b070812..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/rrd_cpu.pl +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl - -use RRDs; - -my $rrdlog = '/var/lib/rrd'; -my $graphs = '/var/lib/rrd'; - -updatecpudata(); -#updatecpugraph('day'); -#updatecpugraph('week'); -#updatecpugraph('month'); -#updatecpugraph('year'); - -sub updatecpugraph { - my $period = $_[0]; - - RRDs::graph ("$graphs/cpu-$period.png", - "--start", "-1$period", "-aPNG", "-i", "-z", - "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", - "--color", "SHADEA#FFFFFF", - "--color", "SHADEB#FFFFFF", - "--color", "BACK#FFFFFF", - "-t cpu usage per $period", - "DEF:user=$rrdlog/cpu.rrd:user:AVERAGE", - "DEF:system=$rrdlog/cpu.rrd:system:AVERAGE", - "DEF:idle=$rrdlog/cpu.rrd:idle:AVERAGE", - - "CDEF:total=user,system,idle,+,+", - "CDEF:userpct=100,user,total,/,*", - "CDEF:systempct=100,system,total,/,*", - "CDEF:idlepct=100,idle,total,/,*", - - "AREA:userpct#0000FF:User cpu usage\\j", - "STACK:systempct#FF0000:system cpu usage\\j", - "STACK:idlepct#00FF00:idle cpu usage\\j"); - - # "GPRINT:userpct:MAX:maximal user cpu\\:%3.2lf%%", - # "GPRINT:userpct:AVERAGE:average user cpu\\:%3.2lf%%", - # "GPRINT:userpct:LAST:current user cpu\\:%3.2lf%%\\j", - # "GPRINT:systempct:MAX:maximal system cpu\\:%3.2lf%%", - # "GPRINT:systempct:AVERAGE:average system cpu\\:%3.2lf%%", - # "GPRINT:systempct:LAST:current system cpu\\:%3.2lf%%\\j", - # "GPRINT:idlepct:MAX:maximal idle cpu\\:%3.2lf%%", - # "GPRINT:idlepct:AVERAGE:average idle cpu\\:%3.2lf%%", - # "GPRINT:idlepct:LAST:current idle cpu\\:%3.2lf%%\\j"); - $ERROR = RRDs::error; - print "Error in RRD::graph for cpu: $ERROR\n" if $ERROR; -} - -sub updatecpudata { - if ( ! -e "$rrdlog/cpu.rrd") { - RRDs::create ("$rrdlog/cpu.rrd", "--step=300", - "DS:user:COUNTER:600:0:U", - "DS:system:COUNTER:600:0:U", - "DS:idle:COUNTER:600:0:U", - - "RRA:AVERAGE:0.5:1:576", - "RRA:AVERAGE:0.5:6:672", - "RRA:AVERAGE:0.5:24:732", - "RRA:AVERAGE:0.5:144:1460"); - $ERROR = RRDs::error; - print "Error in RRD::create for cpu: $ERROR\n" if $ERROR; - } - - my ($cpu, $user, $nice, $system,$idle); - - open STAT, "/proc/stat"; - while() { - chomp; - /^cpu\s/ or next; - ($cpu, $user, $nice, $system, $idle) = split /\s+/; - last; - } - close STAT; - $user += $nice; - - RRDs::update ("$rrdlog/cpu.rrd", - "-t", "user:system:idle", - "N:$user:$system:$idle"); - $ERROR = RRDs::error; - print "Error in RRD::update for cpu: $ERROR\n" if $ERROR; - - print "N:$user:$system:$idle\n"; -} diff --git a/src/com.gluster.storage.management.server.scripts/src/rrd_mem.pl b/src/com.gluster.storage.management.server.scripts/src/rrd_mem.pl deleted file mode 100755 index 5c47cd81..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/rrd_mem.pl +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/perl - -use RRDs; - -my $rrdlog = '/var/lib/rrd'; -my $graphs = '/var/lib/rrd'; - -updatememdata (); -#updatememgraph ('day'); -#updatememgraph ('week'); -#updatememgraph ('month'); -#updatememgraph ('year'); - -sub updatememgraph { - my $period = $_[0]; - - RRDs::graph ("$graphs/memory-$period.png", - "--start", "-1$period", "-aPNG", "-i", "-z", - "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", - "--color", "SHADEA#FFFFFF", - "--color", "SHADEB#FFFFFF", - "--color", "BACK#FFFFFF", - "-t memory usage per $period", - "DEF:used=$rrdlog/mem.rrd:memused:AVERAGE", - "DEF:free=$rrdlog/mem.rrd:memfree:AVERAGE", - "DEF:cache=$rrdlog/mem.rrd:memcache:AVERAGE", - "CDEF:total=used,free,+", - "CDEF:used1=used,buffer,cache,-,-", - "CDEF:usedpct=100,used1,total,/,*", - "CDEF:free1=total,used1,-", - "CDEF:cachepct=100,cache,total,/,*", - "CDEF:freepct=100,free1,total,/,*", - "AREA:usedpct#0000FF:used memory\\j", - "STACK:cachepct#FFFF00:cached memory\\j", - "STACK:freepct#00FF00:free memory\\j"); - $ERROR = RRDs::error; - print "Error in RRD::graph for mem: $ERROR\n" if $ERROR; - - RRDs::graph ("$graphs/swap-$period.png", - "--start", "-1$period", "-aPNG", "-i", "-z", - "--alt-y-grid", "-w 300", "-h 50", "-l 0", "-u 100", "-r", - "--color", "SHADEA#FFFFFF", - "--color", "SHADEB#FFFFFF", - "--color", "BACK#FFFFFF", - "-t swap usage per $period", - "DEF:used=$rrdlog/mem.rrd:swapused:AVERAGE", - "DEF:free=$rrdlog/mem.rrd:swapfree:AVERAGE", - "CDEF:total=used,free,+", - "CDEF:usedpct=100,used,total,/,*", - "CDEF:freepct=100,free,total,/,*", - "AREA:usedpct#0000FF:used swap\\j", - "STACK:freepct#00FF00:free swap\\j"); - $ERROR = RRDs::error; - print "Error in RRD::graph for swap: $ERROR\n" if $ERROR; -} - -sub updatememdata { - my ($memused, $memfree, $memshared, $membuffers, $memcache, $swapused, $swapfree); - if ( ! -e "$rrdlog/mem.rrd") { - RRDs::create ("$rrdlog/mem.rrd", "--step=300", - "DS:memused:ABSOLUTE:600:0:U", - "DS:memfree:ABSOLUTE:600:0:U", - "DS:memcache:ABSOLUTE:600:0:U", - "DS:membuffer:ABSOLUTE:600:0:U", - "DS:swapused:ABSOLUTE:600:0:U", - "DS:swapfree:ABSOLUTE:600:0:U", - "RRA:AVERAGE:0.5:1:576", - "RRA:AVERAGE:0.5:6:672", - "RRA:AVERAGE:0.5:24:732", - "RRA:AVERAGE:0.5:144:1460"); - $ERROR = RRDs::error; - print "Error in RRD::create for mem: $ERROR\n" if $ERROR; - } - - my @memdata = `free -b -o`; - - my $temp = $memdata[1]; - - chomp( $temp ); - my @tempa = split (/\s+/, $temp); - $memused = $tempa [2]; - $memfree = $tempa [3]; - $memshared = $tempa [4]; - $membuffers = $tempa [5]; - $memcache = $tempa [6]; - - $temp = $memdata[2]; - chomp( $temp ); - @tempa = split (/\s+/, $temp); - $swapused = $tempa [2]; - $swapfree = $tempa [3]; - - - RRDs::update ("$rrdlog/mem.rrd", - "-t", "memused:memfree:memcache:membuffer:swapused:swapfree", - "N:$memused:$memfree:$memcache:$membuffers:$swapused:$swapfree"); - - $ERROR = RRDs::error; - print "Error in RRD::update for mem: $ERROR\n" if $ERROR; -} diff --git a/src/com.gluster.storage.management.server.scripts/src/rrd_net.pl b/src/com.gluster.storage.management.server.scripts/src/rrd_net.pl deleted file mode 100755 index 03f4f492..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/rrd_net.pl +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/perl - -use RRDs; - -my $rrdlog = '/var/lib/rrd'; -my $graphs = '/var/lib/rrd'; - -updatenetdata(); -#updatenetgraph('hour'); -#updatenetgraph('day'); -#updatenetgraph('week'); -#updatenetgraph('month'); -#updatenetgraph('year'); - -sub updatenetgraph { - my $period = $_[0]; - - foreach $rrdfile (<$rrdlog/network-*.rrd>) { - RRDs::graph ("$graphs/network-$device-$period.png", - "--start", "-1$period", "-aPNG", "-i", "-z", - "--alt-y-grid", "-w 800", "-h 400", "-l 0", "-u 10000000", "-r", - "--color", "SHADEA#FFFFFF", - "--color", "SHADEB#FFFFFF", - "--color", "BACK#FFFFFF", - "-t $device load per $period", - "DEF:received=$rrdfile:received:AVERAGE", - "DEF:transmitted=$rrdfile:transmitted:AVERAGE", - - "LINE2:received#FF0000:received load\\j", - "LINE1:transmitted#0000FF:transmitted load\\j"); - - $ERROR = RRDs::error; - print "Error in RRD::graph for network $device: $ERROR\n" if $ERROR; - } -} - -sub updatenetdata { - open NETDEV, "/proc/net/dev"; - while () { - chomp; - s/^\s+//; # remove left side whitespaces - /:.+/ or next; # if input line contains ':' else continue - next if /^lo:\s/; # continue if input line starts with 'lo:' - - @tokens1 = split /:/; - @tokens2 = split(/\s+/, $tokens1[1]); - - $device = $tokens1[0]; - $received = $tokens2[0]; - $transmitted = $tokens2[8]; - - #print "$device, $received, $transmitted \n"; - - if ( ! -e "$rrdlog/network-$device.rrd") { - RRDs::create ("$rrdlog/network-$device.rrd", "--step=300", - "DS:received:COUNTER:600:0:U", - "DS:transmitted:COUNTER:600:0:U", - - "RRA:AVERAGE:0.5:1:576", - "RRA:AVERAGE:0.5:6:672", - "RRA:AVERAGE:0.5:24:732", - "RRA:AVERAGE:0.5:144:1460"); - $ERROR = RRDs::error; - print "Error in RRD::create for device $device: $ERROR\n" if $ERROR; - } - - RRDs::update ("$rrdlog/network-$device.rrd", - "-t", "received:transmitted", - "N:$received:$transmitted"); - $ERROR = RRDs::error; - print "Error in RRD::update for net: $ERROR\n" if $ERROR; - } - close NETDEV -} diff --git a/src/com.gluster.storage.management.server.scripts/src/rrd_update_cpu_details.py b/src/com.gluster.storage.management.server.scripts/src/rrd_update_cpu_details.py deleted file mode 100755 index 73982971..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/rrd_update_cpu_details.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -from XmlHandler import ResponseXml -import Utils - -def createMemData(file, step): - rs = ResponseXml() - command = ["rrdtool", "create", file, "--step=%s" % step, - "DS:user:COUNTER:600:0:U", - "DS:system:COUNTER:600:0:U", - "DS:idle:COUNTER:600:0:U", - "RRA:AVERAGE:0.5:1:576", - "RRA:AVERAGE:0.5:6:672", - "RRA:AVERAGE:0.5:24:732", - "RRA:AVERAGE:0.5:144:1460"] - - rv = Utils.runCommand(command, output=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to create RRD file for cpu usages %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return None - -def updateMemData(file): - rs = ResponseXml() - user = None - system = None - idle = None - for line in open("/proc/stat").readlines(): - if line.startswith("cpu"): - cpudetails = line.split() - if "cpu" == cpudetails[0]: - user = cpudetails[1] - system = cpudetails[3] - idle = cpudetails[4] - break - - if None == user: - Utils.log("failed to fetch cpu details from /proc/stat") - rs.appendTagRoute("status.code", "-1") - rs.appendTagRoute("status.message", "failed to fetch cpu details") - return rs.toxml() - - command = ["rrdtool", "update", file, "-t", "user:system:idle", - "N:%s:%s:%s" % (user, system, idle)] - rv = Utils.runCommand(command, output=True, root=True) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message = "Error: [%s]" % (error) - Utils.log("failed to update cpu usage into rrd file %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return None - - -def main(): - cpuRrdFile = "/var/lib/rrd/cpu.rrd" - if not os.path.exists(cpuRrdFile): - status = createMemData(cpuRrdFile, 100) - if status: - print status - status = updateMemData(cpuRrdFile) - if status: - print status - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/rrd_update_memory_details.py b/src/com.gluster.storage.management.server.scripts/src/rrd_update_memory_details.py deleted file mode 100755 index fe4fcce6..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/rrd_update_memory_details.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . -import os -import sys -from XmlHandler import ResponseXml -import Utils - -def createMemData(file, step): - rs = ResponseXml() - command = ["rrdtool", "create", file, "--step=%s" % step, - "DS:memused:ABSOLUTE:600:0:U", - "DS:memfree:ABSOLUTE:600:0:U", - "DS:memcache:ABSOLUTE:600:0:U", - "DS:swapused:ABSOLUTE:600:0:U", - "DS:swapfree:ABSOLUTE:600:0:U", - "RRA:AVERAGE:0.5:1:576", - "RRA:AVERAGE:0.5:6:672", - "RRA:AVERAGE:0.5:24:732", - "RRA:AVERAGE:0.5:144:1460"] - - rv = Utils.runCommand(command, output=True, root=True) - message = Utils.stripEmptyLines(rv["Stdout"]) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to create RRD file for memory usages %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return None - -def updateMemData(file): - rs = ResponseXml() - command = ["free", "-b", "-o"] - rv = Utils.runCommand(command, output=True, root=True) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log("failed to retrieve memory details") - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - - message = rv["Stdout"].split() - command = ["rrdtool", "update", file, "-t", "memused:memfree:memcache:swapused:swapfree", - "N:%s:%s:%s:%s:%s" % (message[8], message[9], message[12], message[14], message[15])] - rv = Utils.runCommand(command, output=True, root=True) - if rv["Stderr"]: - error = Utils.stripEmptyLines(rv["Stderr"]) - message += "Error: [%s]" % (error) - Utils.log(syslog.LOG_ERR, "failed to update memory usage into rrd file %s" % file) - rs.appendTagRoute("status.code", rv["Status"]) - rs.appendTagRoute("status.message", message) - return rs.toxml() - return None - - -def main(): - #if len(sys.argv) != 2: - # print >> sys.stderr, "usage: %s " % sys.argv[0] - # sys.exit(-1) - #step = sys.argv[1] - - memRrdFile = "mem.rrd" - if not os.path.exists(memRrdFile): - status = createMemData(memRrdFile, 100) - if status: - print status - status = updateMemData(memRrdFile) - if status: - print status - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/setup_cifs_config.py b/src/com.gluster.storage.management.server.scripts/src/setup_cifs_config.py deleted file mode 100755 index 2cc35acc..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/setup_cifs_config.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils - -def main(): - try: - os.mkdir(Globals.GLUSTER_BASE_DIR) - os.mkdir(Globals.VOLUME_CONF_DIR) - os.mkdir(Globals.CIFS_EXPORT_DIR) - os.mkdir(Globals.REEXPORT_DIR) - except OSError, e: - Utils.log("failed to create directory: %s" % str(e)) - sys.exit(1) - try: - fp = open(Globals.VOLUME_SMBCONF_FILE, "w") - fp.close() - except IOError, e: - Utils.log("Failed to create file %s: %s" % (Globals.VOLUME_SMBCONF_FILE, str(e))) - sys.exit(2) - try: - os.rename(Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE) - except IOError, e: - Utils.log("Ignoring rename %s to %s: %s" % (Globals.SAMBA_CONF_FILE, "%s.orig" % Globals.SAMBA_CONF_FILE, str(e))) - try: - fp = open(Globals.SAMBA_CONF_FILE, "w") - fp.write("##\n") - fp.write("## THIS FILE SHOULD NOT BE MODIFIED. IF YOU WANT TO MODIFY SAMBA\n") - fp.write("## CONFIGURATIONS, USE /etc/samba/real.smb.conf FILE\n") - fp.write("##\n") - fp.write("include = %s\n\n" % Globals.REAL_SAMBA_CONF_FILE) - fp.write("## CAUTION: DO NOT REMOVE BELOW LINE. REMOVAL OF THE LINE DISABLES\n") - fp.write("## CIFS REEXPORT OF GLUSTER VOLUMES\n") - fp.write("include = %s\n" % Globals.VOLUME_SMBCONF_FILE) - fp.close() - except IOError, e: - Utils.log("Failed to create samba configuration file %s: %s" % (Globals.SAMBA_CONF_FILE, str(e))) - sys.exit(3) - try: - fp = open(Globals.REAL_SAMBA_CONF_FILE, "w") - fp.write("[global]\n") - fp.write("## CAUTION: DO NOT REMOVE BELOW INCLUDE LINE. REMOVAL OF THE LINE\n") - fp.write("## DISABLES SERVER/CIFS HIGH AVAILABILITY\n") - #fp.write("include = %s\n" % Globals.CTDB_SAMBA_CONF_FILE) - fp.write("##\n") - fp.write("socket options = TCP_NODELAY IPTOS_LOWDELAY SO_SNDBUF=131072 SO_RCVBUF=131072\n") - fp.write("read raw = yes\n") - fp.write("server string = %h\n") - fp.write("write raw = yes\n") - fp.write("oplocks = yes\n") - fp.write("max xmit = 131072\n") - fp.write("dead time = 15\n") - fp.write("getwd cache = yes\n") - fp.write("#read size = 131072\n") - fp.write("use sendfile=yes\n") - fp.write("block size = 131072\n") - fp.write("printcap name = /etc/printcap\n") - fp.write("load printers = no\n") - fp.close() - except IOError, e: - Utils.log("Failed to create samba configuration file %s: %s" % (Globals.REAL_SAMBA_CONF_FILE, str(e))) - sys.exit(4) - - - if Utils.runCommand("setsebool -P samba_share_fusefs on") != 0: - Utils.log("failed to set SELinux samba_share_fusefs") - sys.exit(5) - - if Utils.runCommand("service smb restart") != 0: - Utils.log("failed to restart smb service") - sys.exit(6) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/start_volume_cifs.py b/src/com.gluster.storage.management.server.scripts/src/start_volume_cifs.py deleted file mode 100755 index 239216c3..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/start_volume_cifs.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils -import VolumeUtils - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - - volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) - cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName) - - if Utils.runCommand("mount -t glusterfs 127.0.0.1:%s %s" % (volumeName, volumeMountDirName)) != 0: - Utils.log("Failed to mount volume %s" % (volumeName)) - sys.exit(1) - if Utils.runCommand("ln -fTs %s %s" % (volumeMountDirName, cifsDirName)) != 0: - Utils.log("Failed to create reexport link %s" % cifsDirName) - sys.exit(2) - if Utils.runCommand("chcon -t samba_share_t %s -h" % cifsDirName) != 0: - Utils.log("Failed to change security context for the link %s" % cifsDirName) - sys.exit(2) - if not VolumeUtils.includeVolume(volumeName): - Utils.log("Failed to include volume for CIFS reexport") - sys.exit(3) - if Utils.runCommand("service smb reload") != 0: - Utils.log("Failed to reload smb service") - sys.exit(4) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server.scripts/src/stop_volume_cifs.py b/src/com.gluster.storage.management.server.scripts/src/stop_volume_cifs.py deleted file mode 100755 index 99ac4750..00000000 --- a/src/com.gluster.storage.management.server.scripts/src/stop_volume_cifs.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Globals -import Utils -import VolumeUtils - -def main(): - if len(sys.argv) != 2: - sys.stderr.write("usage: %s VOLUME_NAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - volumeName = sys.argv[1] - - volumeMountDirName = "%s/%s" % (Globals.REEXPORT_DIR, volumeName) - cifsDirName = "%s/%s" % (Globals.CIFS_EXPORT_DIR, volumeName) - - if not Utils.removeFile(cifsDirName): - Utils.log("Failed to remove reexport link %s" % cifsDirName) - sys.exit(1) - if not VolumeUtils.excludeVolume(volumeName): - Utils.log("Failed to exclude volume for CIFS reexport") - sys.exit(2) - if Utils.runCommand("service smb reload") != 0: - Utils.log("Failed to reload smb service") - sys.exit(3) - if Utils.runCommand("umount %s" % (volumeMountDirName)) != 0: - Utils.log("Failed to unmount volume %s" % (volumeName)) - sys.exit(4) - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server/.classpath b/src/com.gluster.storage.management.server/.classpath deleted file mode 100644 index 107e139d..00000000 --- a/src/com.gluster.storage.management.server/.classpath +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/.project b/src/com.gluster.storage.management.server/.project deleted file mode 100644 index 3e4dc06a..00000000 --- a/src/com.gluster.storage.management.server/.project +++ /dev/null @@ -1,41 +0,0 @@ - - - com.gluster.storage.management.gateway - - - - - - org.python.pydev.PyDevBuilder - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.jdt.core.javanature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/src/com.gluster.storage.management.server/.settings/.jsdtscope b/src/com.gluster.storage.management.server/.settings/.jsdtscope deleted file mode 100644 index 3a28de0c..00000000 --- a/src/com.gluster.storage.management.server/.settings/.jsdtscope +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 476db350..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -#Wed Dec 29 14:57:23 IST 2010 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs deleted file mode 100644 index 5d9c71b6..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.ltk.core.refactoring.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Mon Jan 31 15:29:36 IST 2011 -eclipse.preferences.version=1 -org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 3d5a50bf..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 8f960f27..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a4..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs b/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index e5ca6272..00000000 --- a/src/com.gluster.storage.management.server/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Mon Jan 31 15:29:36 IST 2011 -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF b/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF deleted file mode 100644 index 5e949512..00000000 --- a/src/com.gluster.storage.management.server/WebContent/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: - diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/antlr-2.7.6.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/antlr-2.7.6.jar deleted file mode 100644 index 3702b645..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/antlr-2.7.6.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar deleted file mode 100644 index 578b1a0c..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/aopalliance-1.0.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar deleted file mode 100644 index 8217cae0..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/asm-3.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-collections-3.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-collections-3.1.jar deleted file mode 100644 index 41e230fe..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-collections-3.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar deleted file mode 100644 index 8758a96b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/commons-logging-1.1.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar deleted file mode 100644 index dc8ae8df..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derby.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar deleted file mode 100644 index ca367aae..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/derbytools.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/dom4j-1.6.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/dom4j-1.6.1.jar deleted file mode 100644 index c8c4dbb9..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/dom4j-1.6.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt deleted file mode 100644 index 3eddd42f..00000000 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250-LICENSE.txt +++ /dev/null @@ -1,87 +0,0 @@ -Copyright (c) 2006 - 2010 Christian Plattner. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -a.) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -b.) Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -c.) Neither the name of Christian Plattner nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -This software includes work that was released under the following license: - -Copyright (c) 2005 - 2006 Swiss Federal Institute of Technology (ETH Zurich), - Department of Computer Science (http://www.inf.ethz.ch), - Christian Plattner. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -a.) Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -b.) Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -c.) Neither the name of ETH Zurich nor the names of its contributors may - be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -The Java implementations of the AES, Blowfish and 3DES ciphers have been -taken (and slightly modified) from the cryptography package released by -"The Legion Of The Bouncy Castle". - -Their license states the following: - -Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle -(http://www.bouncycastle.org) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar deleted file mode 100644 index c0a9ac7b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/ganymed-ssh2-build250.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar deleted file mode 100644 index 4c9ac4e9..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate-jpa-2.0-api-1.0.0.Final.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate3.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate3.jar deleted file mode 100644 index c1c81141..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/hibernate3.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar deleted file mode 100644 index a3248188..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-core-asl-1.5.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar deleted file mode 100644 index faf12cf6..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-jaxrs-1.5.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar deleted file mode 100644 index ca612580..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-mapper-asl-1.5.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar deleted file mode 100644 index 57c2c670..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jackson-xc-1.5.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar deleted file mode 100644 index 8f692f4f..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/javassist-3.12.0.GA.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar deleted file mode 100644 index 62f790fa..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-client-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar deleted file mode 100644 index 92b38466..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-core-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar deleted file mode 100644 index 01d8c83b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-json-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar deleted file mode 100644 index 1c134f05..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-multipart-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar deleted file mode 100644 index a29d7409..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-server-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar deleted file mode 100644 index c79b4490..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jersey-spring-1.5.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar deleted file mode 100644 index e4e9c8c3..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jettison-1.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar deleted file mode 100644 index 23782c02..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jnlp-servlet.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar deleted file mode 100644 index ec8bc818..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jsr311-api-1.1.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jta-1.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jta-1.1.jar deleted file mode 100644 index 6d225b76..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/jta-1.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/log4j-1.2.16.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/log4j-1.2.16.jar deleted file mode 100644 index 3f9d8476..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/log4j-1.2.16.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/mimepull-1.3.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/mimepull-1.3.jar deleted file mode 100644 index 48cc9295..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/mimepull-1.3.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar deleted file mode 100644 index a5d37aa1..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.eclipse.equinox.common_3.6.0.v20100503.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar deleted file mode 100644 index db6f529f..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aop-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar deleted file mode 100644 index 7cd3a626..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.asm-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar deleted file mode 100644 index 11fc11b9..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.aspects-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar deleted file mode 100644 index f2e2e927..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.beans-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar deleted file mode 100644 index bd1367d8..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar deleted file mode 100644 index e46f9eb8..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.context.support-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar deleted file mode 100644 index ea9500d6..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.core-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar deleted file mode 100644 index 6ef99d8d..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.expression-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar deleted file mode 100644 index e149290e..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar deleted file mode 100644 index dcd1e4d9..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar deleted file mode 100644 index f7a3b837..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jdbc-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar deleted file mode 100644 index 9cea2aef..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.jms-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar deleted file mode 100644 index d0550ccd..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.orm-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar deleted file mode 100644 index 1688cf74..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.oxm-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd deleted file mode 100644 index b3aa6af8..00000000 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.spring-library-3.0.5.RELEASE.libd +++ /dev/null @@ -1,21 +0,0 @@ -Library-SymbolicName: org.springframework.spring -Library-Version: 3.0.5.RELEASE -Library-Name: Spring Framework -Import-Bundle: - org.springframework.aop;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.asm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.aspects;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.beans;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.context;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.context.support;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.core;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.expression;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.jdbc;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.jms;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.orm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.oxm;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.transaction;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.web;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.web.servlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - org.springframework.web.portlet;version="[3.0.5.RELEASE, 3.0.5.RELEASE]", - com.springsource.org.aopalliance;version="[1.0.0, 1.0.0]" diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar deleted file mode 100644 index 237995c5..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.test-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar deleted file mode 100644 index 2f52122b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.transaction-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar deleted file mode 100644 index 5a2381a0..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar deleted file mode 100644 index 6ec9d681..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.portlet-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar deleted file mode 100644 index 6d13bd40..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.servlet-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar deleted file mode 100644 index e351ae7b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/org.springframework.web.struts-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar deleted file mode 100644 index 56222cbf..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.client_1.0.0.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar deleted file mode 100644 index d321e76c..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/plugins/com.gluster.storage.management.core_1.0.0.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar deleted file mode 100644 index e5bc672b..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/servlet-api.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar deleted file mode 100644 index f1f4fdd2..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/slf4j-api-1.6.1.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar deleted file mode 100644 index 78818fc5..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-config-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar deleted file mode 100644 index a8077d5d..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-core-3.0.5.RELEASE.jar and /dev/null differ diff --git a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar b/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar deleted file mode 100644 index 26611b55..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/WEB-INF/lib/spring-security-web-3.0.5.RELEASE.jar and /dev/null differ 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 deleted file mode 100644 index 631788ff..00000000 --- a/src/com.gluster.storage.management.server/WebContent/WEB-INF/web.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - glustermg - - index.html - index.htm - index.jsp - default.html - default.htm - default.jsp - - - contextConfigLocation - - classpath:spring/gluster-server-security.xml - classpath:spring/gluster-server-base.xml - - - - org.springframework.web.context.ContextLoaderListener - - - org.springframework.web.context.request.RequestContextListener - - - gluster-resources-1.0 - com.sun.jersey.spi.spring.container.servlet.SpringServlet - - com.sun.jersey.config.property.packages - com.gluster.storage.management.gateway.resources.v1_0 - - - com.sun.jersey.spi.container.ResourceFilters - com.gluster.storage.management.gateway.filters.GlusterResourceFilterFactory - - 1 - - - gluster-resources-1.0 - /1.0/* - - - JnlpDownloadServlet - jnlp.sample.servlet.JnlpDownloadServlet - - - JnlpDownloadServlet - *.jnlp - - - JnlpDownloadServlet - *.jar - - - springSecurityFilterChain - - org.springframework.web.filter.DelegatingFilterProxy - - - - springSecurityFilterChain - /* - - - - Gluster Management Gateway - /* - - - CONFIDENTIAL - - - \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/0-version.sql b/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/0-version.sql deleted file mode 100644 index 4c3d81d1..00000000 --- a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/0-version.sql +++ /dev/null @@ -1,2 +0,0 @@ -create table version (version varchar(16) not null primary key); -insert into version(version) values('1.0.0'); \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/1-security-schema.sql b/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/1-security-schema.sql deleted file mode 100644 index fdde5823..00000000 --- a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/1-security-schema.sql +++ /dev/null @@ -1,26 +0,0 @@ -create table users( - username varchar(50) not null primary key, - password varchar(50) not null, - enabled smallint not null - ); - - create table authorities ( - username varchar(50) not null, - authority varchar(50) not null, - constraint fk_authorities_users foreign key(username) references users(username)); - create unique index ix_auth_username on authorities (username,authority); - -create table groups ( - id bigint generated by default as identity(start with 0) primary key, - group_name varchar(50) not null); - -create table group_authorities ( - group_id bigint not null, - authority varchar(50) not null, - constraint fk_group_authorities_group foreign key(group_id) references groups(id)); - -create table group_members ( - id bigint generated by default as identity(start with 0) primary key, - username varchar(50) not null, - group_id bigint not null, - constraint fk_group_members_group foreign key(group_id) references groups(id)); diff --git a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql b/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql deleted file mode 100644 index 35ccf965..00000000 --- a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/2-users-authorities-groups.sql +++ /dev/null @@ -1,21 +0,0 @@ --- Create users -insert into users(username, password, enabled) values ('gluster','gluster',1); -insert into users(username, password, enabled) values ('guest','guest',1); - --- Assign authorities to users (to be removed after implementing user group functionality) -insert into authorities(username,authority) values ('gluster','ROLE_USER'); -insert into authorities(username,authority) values ('gluster','ROLE_ADMIN'); -insert into authorities(username,authority) values ('guest','ROLE_USER'); - --- Create user groups -insert into groups(group_name) values ('Users'); -insert into groups(group_name) values ('Administrators'); - --- Add authorities to groups (functionality not yet implemented in code) -insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Users'; -insert into group_authorities(group_id, authority) select id,'ROLE_USER' from groups where group_name='Administrators'; -insert into group_authorities(group_id, authority) select id,'ROLE_ADMIN' from groups where group_name='Administrators'; - --- Assign group members -insert into group_members(group_id, username) select id,'guest' from groups where group_name='Users'; -insert into group_members(group_id, username) select id,'gluster' from groups where group_name='Administrators'; \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/3-cluster-servers.sql b/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/3-cluster-servers.sql deleted file mode 100644 index 17ca62d2..00000000 --- a/src/com.gluster.storage.management.server/WebContent/data/scripts/1.0.0/3-cluster-servers.sql +++ /dev/null @@ -1,16 +0,0 @@ -create table cluster_info ( - id bigint generated by default as identity, - name varchar(255), - primary key (id)); - -create unique index ix_cluster_name on cluster_info (name); - -create table server_info ( - id bigint generated by default as identity, - name varchar(255), - cluster_id bigint, - primary key (id)); - -create unique index ix_cluster_server on server_info (name, cluster_id); - -alter table server_info add constraint FK_CLUSTER_ID foreign key (cluster_id) references cluster_info(id); \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/WebContent/index.html b/src/com.gluster.storage.management.server/WebContent/index.html deleted file mode 100644 index 4c90162a..00000000 --- a/src/com.gluster.storage.management.server/WebContent/index.html +++ /dev/null @@ -1,8 +0,0 @@ - - -Gluster Management Console - - -TODO: Identify the client's platform-browser and invoke appropriate JNLP URL. - - diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py b/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py deleted file mode 100644 index f8a07c25..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/Globals.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -MULTICAST_GROUP = '224.224.1.1' -MULTICAST_PORT = 5353 -GLUSTER_PLATFORM_VERSION = "3.2" - -## System configuration constants -SYSCONFIG_NETWORK_DIR = "/etc/sysconfig/network-scripts" -DNSMASQ_CONF_DIR = "/etc/dnsmasq.d" - -FSTAB_FILE = "/etc/fstab" -NFS_EXPORTS_FILE = "/etc/exports" -SAMBA_CONF_FILE = "/etc/samba/smb.conf" -TIMEZONE_FILE = "/etc/timezone" -ZONEINFO_DIR = "/usr/share/zoneinfo" -LOCALTIME_FILE = "/etc/localtime" -KERBEROS_CONF_FILE = "/etc/krb5.conf" -NSSWITCH_CONF_FILE = "/etc/nsswitch.conf" -NTP_CONF_FILE = "/etc/ntp.conf" -MODPROBE_CONF_FILE = "/etc/modprobe.d/bonding.conf" -SYSCONFIG_NETWORK_FILE = "/etc/sysconfig/network" -RESOLV_CONF_FILE = "/etc/resolv.conf" -DNSMASQ_LEASE_FILE = "/var/tmp/dnsmasq.leases" -LIVE_MODE_FILE = "/etc/live" -ADD_SERVER_COMPLETED_FILE = "/var/tmp/installation-completed" - -DNSMASQ_DNS_CONF_FILE = DNSMASQ_CONF_DIR + "/dns.conf" -DNSMASQ_DHCP_CONF_FILE = DNSMASQ_CONF_DIR + "/dhcp.conf" -## - -## Base constants -MAX_PARTITION_SIZE = 16777216 # 16 TB -OS_PARTITION_SIZE = 4000 # 4 GB -SESSION_TIMEOUT = 1800 # 30 minutes -SERVER_AGENT_PORT = 50000 - -BOOT_PARTITION_LABEL = "GLUSTEROS" -DATA_PARTITION_LABEL = "GLUSTERDATA" -VOLUME_USER_DESCRIPTION = "Gluster Volume User" -SERVER_AGENT_RUN_USERNAME = "gluster" -INSTALLER_SERVER_NAME = "$installer$" - -GLUSTER_BASE_DIR = "/etc/glustermg" -GLUSTER_LUN_DIR = "/data" -REEXPORT_DIR = "/reexport" -NFS_EXPORT_DIR = "/nfs" -CIFS_EXPORT_DIR = "/cifs" -WEBDAV_DOCUMENT_ROOT_DIR = "/var/www/html" -UPDATES_DIR = "/UPDATES" -TRANSPORT_HOME_DIR = "/transport" -GLUSTERFS_LOG_DIR = "/var/log/glusterfs" -LOG_DIR = "/var/log/glustermg" - -GLUSTER_UPDATES_FILE = "updates.xml" -INSTALLER_STATUS_FILE = "/var/log/install-server-status.log" -INSTALL_PLATFORM_LOCK_FILE = "/var/lock/install-gluster-platform.lock" -LAST_ACCESSED_NETWORK_FILE = "last-accessed-network" -PREPARE_DATA_DISK_LOCK_FILE = "/var/tmp/prepare-data-disk.lock" -## - -## Derived constants -GLUSTER_CONF_DIR = GLUSTER_BASE_DIR + "/conf" -GLUSTER_TMP_DIR = GLUSTER_BASE_DIR + "/tmp" -VOLUME_CONF_DIR = GLUSTER_BASE_DIR + "/volumes" -SERVER_CONF_DIR = GLUSTER_BASE_DIR + "/servers" -DNS_RECORDS_DIR = GLUSTER_BASE_DIR + "/dns-records" -INSTALLER_CONF_DIR = SERVER_CONF_DIR + "/" + INSTALLER_SERVER_NAME - -GSN_USER_INFO_FILE = GLUSTER_BASE_DIR + "/gsn-user.info" -GLUSTER_VERSION_FILE = GLUSTER_BASE_DIR + "/version" -GLUSTER_UPDATE_SITE_FILE = GLUSTER_BASE_DIR + "/update-site" -GLUSTER_DIRECTORY_SERVICE_CONF_FILE = GLUSTER_BASE_DIR + "/directory.xml" -GLUSTER_TIME_CONF_FILE = GLUSTER_BASE_DIR + "/timeconfig.xml" -TRANSACTION_KEY_FILE = GLUSTER_BASE_DIR + "/transaction.key" -SERVER_COUNT_FILE = GLUSTER_BASE_DIR + "/server-count" -SIGNATURE_FILE = GLUSTER_BASE_DIR + "/.signature" -GLUSTER_SERVER_POOL_FILE = GLUSTER_BASE_DIR + "/pool" -GLUSTER_ADMIN_FILE = GLUSTER_BASE_DIR + "/.password" - -VOLUME_SMBCONF_FILE = VOLUME_CONF_DIR + "/volumes.smbconf.list" - -GLOBAL_NETWORK_FILE = INSTALLER_CONF_DIR + "/network.xml" -INSTALL_SERVER_CONF_FILE = INSTALLER_CONF_DIR + "/installer.xml" -INSTALLER_INFO_FILE = INSTALLER_CONF_DIR + "/installer.info" -INSTALLED_SERVER_COUNT_FILE = INSTALLER_CONF_DIR + "/installed-server-count" - -SESSION_FILE = GLUSTER_TMP_DIR + "/login.sessions" - -GENERAL_LOG_FILE = LOG_DIR + "/general.log" -INSTALLER_LOG_FILE = LOG_DIR + "/installer.log" -PEER_AGENT_LOG_FILE = LOG_DIR + "/peeragent.log" -SERVER_AGENT_LOG_FILE = LOG_DIR + "/serveragent.log" -TRANSPORT_AGENT_LOG_FILE = LOG_DIR + "/transport.log" -## - - -## Global variables -## TODO: These should be removed -DOWNLOAD_GLUSTER_UPDATE_PROCESS = None -DOWNLOAD_GLUSTER_UPDATE_LEVEL = None -DOWNLOAD_GLUSTER_CURRENT_UPDATE_LEVEL = None -DOWNLOAD_GLUSTER_UPDATE_MD5SUM = None -REQUEST_MAP = {} -VERSION_DICTONARY = {} -## - -AWS_WEB_SERVICE_URL = "http://169.254.169.254/latest" -REAL_SAMBA_CONF_FILE = "/etc/samba/real.smb.conf" diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py b/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py deleted file mode 100644 index ff073593..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/Protocol.py +++ /dev/null @@ -1,438 +0,0 @@ -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import xml -import xml.parsers.expat -import xml.dom.minidom as MDOM -import os -import Globals -import copy -import Utils - -XML_STRING = 0 -XML_FILE = 1 - -class XDOM: - _domObj = None - - def __init__(self): - self._domObj = MDOM.Document() - return - - @classmethod - def getText(self, nodeList): - rc = "" - for node in nodeList: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc.strip() - - def parseString(self, requestString): - try: - self._domObj = MDOM.parseString(requestString) - except xml.parsers.expat.ExpatError, e: - Utils.log("XML string parse error: %s" % str(e)) - return False - return True - - def parseFile(self, fileName): - try: - self._domObj = MDOM.parse(fileName) - except IOError, e: - Utils.log("error reading file: %s" % str(e)) - return False - except xml.parsers.expat.ExpatError, e: - Utils.log("XML file %s parse error: %s" % (fileName, str(e))) - return False - return True - - def setDomObj(self, dom): - if dom and type(dom) != type([]): - self._domObj = dom - return True - return False - - def createTextNode(self, text): - if not self._domObj: - return False - if not text: - return False - return self._domObj.createTextNode(str(text)) - - def createTag(self, tag, text=None): - if not self._domObj: - return None - if tag == None: - return None - - tagE = self._domObj.createElement(str(tag)) - if text: - tagEText = self._domObj.createTextNode(str(text)) - tagE.appendChild(tagEText) - return tagE - - def addTag(self, tag): - if not self._domObj: - return False - if not tag: - return False - - self._domObj.appendChild(tag) - return True - - def createTagRoute(self, tagRoute, text=None): - if not tagRoute: - return False - - tagList = tagRoute.split(".") - tag = None - previousTag = None - for tagName in tagList[:-1]: - newTag = self.createTag(tagName, None) - if not tag: - tag = newTag - previousTag = newTag - continue - previousTag.appendChild(newTag) - previousTag = newTag - - if previousTag: - previousTag.appendChild(self.createTag(tagList[-1], text)) - else: - tag = self.createTag(tagList[-1], text) - return tag - - def appendTagRoute(self, tagRoute, value=None): - if not self._domObj: - return False - if not tagRoute: - return False - - parentTagE = self._domObj - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def setTextByTagRoute(self, tagRoute, tagValue): - if not self._domObj: - return None - - if not tagRoute: - return None - - tagE = self.getElementsByTagRoute(tagRoute) - if not tagE: - return False - - parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) - if not parentTagE: - return False - - parentTagE[0].childNodes.remove(tagE[0]) - parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) - return True - - def getElementsByTagRoute(self, tagRoute): - if not self._domObj: - return None - - if not tagRoute: - return None - - x = None - for tag in tagRoute.split("."): - if x is None: - x = self._domObj.getElementsByTagName(tag) - continue - if x == []: - break - x = x[0].getElementsByTagName(tag) - return x - - def getTextByTagRoute(self, tagRoute): - if not self._domObj: - return None - - x = self.getElementsByTagRoute(tagRoute) - if x: - return self.getText(x[0].childNodes) - return None - - def getElementsByTagName(self, name): - if not self._domObj: - return None - return self._domObj.getElementsByTagName(name) - - def writexml(self, fileName, indent="", addindent="", newl=""): - if not self._domObj: - return None - try: - fp = open(fileName, "w") - self._domObj.writexml(fp, indent, addindent, newl) - fp.close() - return True - except IOError: - return False - - def toString(self, indent=" ", newl="\n", encoding = None): - if not self._domObj: - return None - return self._domObj.toprettyxml(indent, newl, encoding) - - def toxml(self, encoding = None): - if not self._domObj: - return None - return self._domObj.toxml(encoding) - - def toprettyxml(self, indent=" ", newl="\n", encoding = None): - return self.toString(indent, newl, encoding) - - def getAttribute(self, attributeName): - if not attributeName: - return None - try: - return self.getElementsByTagName("command")[0].getAttribute(attributeName) - except IndexError: - return False - - def setAttribute(self, attributeName, attributeValue): - if not (attributeName and attributeValue): - return None - try: - return self.getElementsByTagName("command")[0].setAttribute(attributeName, attributeValue) - except IndexError: - return False - - def getRequestCommand(self): - return self.getAttribute("request") - - def getResponseCommand(self): - return self.getAttribute("response") - - def getResponseCode(self): - return self.getAttribute("response-code") - - def getMessageId(self): - return self.getAttribute("id") - - def getVersion(self): - return self.getAttribute("version") - - def getRequestAction(self): - return self.getAttribute("action") - - def setVersion(self, value): - return self.setAttribute("version", value) - - def setRequestAction(self, value): - return self.setAttribute("action", value) - - def createCommandTag(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - commandTag = self._domObj.createElement("command") - commandTag.setAttribute("response", command) - commandTag.setAttribute("response-code", responseCode) - commandTag.setAttribute("id", id) - commandTag.setAttribute("version", version) - return commandTag -##--end of XDOM - -class RequestXml(XDOM): - def __init__(self, requestString, type=None): - if None == requestString: - XDOM.__init__(self) - return - try: - if None == type: - if os.path.isfile(requestString): - self._domObj = MDOM.parse(requestString) - else: - self._domObj = MDOM.parseString(requestString) - elif XML_FILE == type: - self._domObj = MDOM.parse(requestString) - elif XML_STRING == type: - self._domObj = MDOM.parseString(requestString) - except IOError: - XDOM.__init__(self) - except xml.parsers.expat.ExpatError: - XDOM.__init__(self) - -##--end of RequestXML - -class ResponseXml(XDOM): - _commandTag = None - def __init__(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - XDOM.__init__(self) - if command and responseCode and id: - self._commandTag = self.createCommandTag(command, responseCode, id, version) - self._domObj.appendChild(self._commandTag) - - def appendCommand(self, command, responseCode, id, version=Globals.GLUSTER_PLATFORM_VERSION): - if command and responseCode and id: - self._commandTag = self.createCommandTag(command, responseCode, id, version) - self._domObj.appendChild(self._commandTag) - return True - return False - - def append(self, tagName, tagValue=None): - if not self._commandTag: - return False - tag = self.createTag(tagName, tagValue) - if tag: - self._commandTag.appendChild(tag) - return True - return False - - def appendTag(self, tag): - if not tag: - return False - if not self._commandTag: - return False - self._commandTag.appendChild(tag) - return True - - def appendTagRoute(self, tagRoute, value=None): - if not self._commandTag: - return False - if not tagRoute: - return False - - parentTagE = self._commandTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["command"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def appendTagRouteOld(self, tagRoute, value=None): - if not tagRoute: - return False - if not self._commandTag: - return False - - tmpTagRoute = "" - previousTagE = self._commandTag - tagE = None - for tagName in tagRoute.split("."): - if not tmpTagRoute: - tagE = self.getElementsByTagRoute("command." + tagName) - else: - tagE = self.getElementsByTagRoute("command." + tmpTagRoute + "." + tagName) - if not tagE: - break - if len(tagE) != 1: - return False - previousTagE = tagE[0] - if not tmpTagRoute: - tmpTagRoute = tagName - else: - tmpTagRoute = tmpTagRoute + "." + tagName - - if tmpTagRoute == tagRoute: - return False - newTagRoute = tagRoute[len(tmpTagRoute):] - if newTagRoute[0] == '.': - newTagRoute = newTagRoute[1:] - - if previousTagE.childNodes and previousTagE.childNodes[0].nodeType == previousTagE.TEXT_NODE: - return False - previousTagE.appendChild(self.createTagRoute(newTagRoute, value)) - return True -##--end of ResponseXml - -def test(): - #volumes = RequestXml(VolumeFile, XML_FILE).getElementsByTagRoute("volume-list.volume") - requestStr = ''' - -movies1 -cluster mirror -512000 -zresearch -192.168.20.* -192.168.30.* - -no - - -no - - -no - - -''' - - requestXml = RequestXml(requestStr) - print requestXml.getAttribute("") - -def test1(): - rs = ResponseXml("create-volume", "OK", "xyz") - rs.appendTagRoute("volume.detail.name", "music") - print rs.toprettyxml() - rs.append("volume", "data") - print rs.toprettyxml() - rs.appendTagRoute("volume.detail.ipaddr", "192.168.10.1") - print rs.toprettyxml() - print rs.appendTagRoute("volume.detail.ipaddr.v6", "ff:ff::ff::") - print rs.toprettyxml() - - print rs.getTextByTagRoute("command.volume.detail") - -def test2(): - rs = ResponseXml("download-volume-logs", "OK", "xyz") - te = rs.createTag("interface", None) - te.appendChild(rs.createTag("device", "DEVICE1")) - te.appendChild(rs.createTag("description", "my device one")) - rs.appendTag(te) - - te = rs.createTag("interface", None) - te.appendChild(rs.createTag("device", "DEVICE2")) - te.appendChild(rs.createTag("description", "my device two")) - rs.appendTag(te) - print rs.toprettyxml() - diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/Utils.py b/src/com.gluster.storage.management.server/WebContent/scripts/Utils.py deleted file mode 100644 index 3408c14a..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/Utils.py +++ /dev/null @@ -1,1059 +0,0 @@ -# Copyright (c) 2010 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import os -import re -import socket -import struct -import syslog -import subprocess -#import spwd -import time -#import uuid -import tempfile -import grp -import pwd -import inspect -from datetime import datetime -import urllib - -import Globals -import Protocol - -RUN_COMMAND_ERROR = -1024 -LOG_SYSLOG = 1 -SYSLOG_REQUIRED = False -LOG_FILE_NAME = None -LOG_FILE_OBJ = None - - -def _getLogCode(priority): - if syslog.LOG_EMERG == priority: - return "M" - elif syslog.LOG_ALERT == priority: - return "A" - elif syslog.LOG_CRIT == priority: - return "C" - elif syslog.LOG_ERR == priority: - return "E" - elif syslog.LOG_WARNING == priority: - return "W" - elif syslog.LOG_NOTICE == priority: - return "N" - elif syslog.LOG_INFO == priority: - return "I" - elif syslog.LOG_DEBUG == priority: - return "D" - else: # UNKNOWN - return "X" - - -def setLogFile(fileName): - global LOG_FILE_NAME - - if fileName: - LOG_FILE_NAME = fileName - return True - return False - - -def closeLog(): - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - if SYSLOG_REQUIRED: - syslog.closelog() - SYSLOG_REQUIRED = False - return True - - if LOG_FILE_OBJ: - try: - LOG_FILE_OBJ.close() - LOG_FILE_OBJ = None - except IOError, e: - sys.stderr.write("Failed to close file: %s\n" % e) - return False - return True - - -def openLog(fileName=None): - global LOG_FILE_NAME - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - if fileName == LOG_SYSLOG: - syslog.openlog(os.path.basename(sys.argv[0])) - SYSLOG_REQUIRED = True - return True - - if fileName: - LOG_FILE_NAME = fileName - - if not LOG_FILE_NAME: - return False - - closeLog() - - try: - LOG_FILE_OBJ = open(LOG_FILE_NAME, "a") - except IOError, e: - sys.stderr.write("Failed to open file %s: %s\n" % (LOG_FILE_NAME, e)) - return False - return True - -def record(priority, message=None): - global LOG_FILE_OBJ - global SYSLOG_REQUIRED - - stack = inspect.stack()[1] - if stack[3] == "": - prefix = "%s:%s:%s" % (stack[1], stack[2], stack[3]) - else: - prefix = "%s:%s:%s()" % (stack[1], stack[2], stack[3]) - - if type(priority) == type("") or type(priority) == type(u""): - logPriority = syslog.LOG_INFO - logMessage = priority - else: - logPriority = priority - logMessage = message - - if SYSLOG_REQUIRED: - syslog.syslog(logPriority, "[%s]: %s" % (prefix, logMessage)) - return - - fp = sys.stderr - if LOG_FILE_OBJ: - fp = LOG_FILE_OBJ - - fp.write("[%s] %s [%s]: %s" % (str(datetime.now()), _getLogCode(logPriority), prefix, logMessage)) - if logMessage[-1] != '\n': - fp.write("\n") - fp.flush() - return - - -def trace(message): - if message: - log(syslog.LOG_DEBUG, message) - - -def isString(value): - return (type(value) == type("") or type(value) == type(u"")) - - -def getTempFileName(): - filedesc, filename = tempfile.mkstemp(prefix="GSP_") - os.close(filedesc) - return filename - - -def runCommandBG(command, stdinFileObj=None, stdoutFileObj=None, stderrFileObj=None, - shell=False, root=None): - log("runCommandBG(): Trying to execute command [%s]" % command) - - if shell: - if not isString(command): - return None - else: - if isString(command): - command = command.split() - - if root == True: - if shell: - command = "sudo " + command - else: - command = ['sudo'] + command - elif isString(root): - if shell: - command = "sudo -u " + root + " " + command - else: - command = ['sudo', '-u', root] + command - - if not stdinFileObj: - stdinFileObj=subprocess.PIPE - if not stdoutFileObj: - stdoutFileObj=subprocess.PIPE - if not stderrFileObj: - stderrFileObj=subprocess.PIPE - - try: - process = subprocess.Popen(command, - bufsize=-1, - stdin=stdinFileObj, - stdout=stdoutFileObj, - stderr=stderrFileObj, - shell=shell) - return process - except OSError, e: - log("runCommandBG(): Failed to run command [%s]: %s" % (command, e)) - return None - - -def runCommand(command, - input='', output=False, - shell=False, root=None): - rv = {} - rv["Status"] = RUN_COMMAND_ERROR - rv["Stdout"] = None - rv["Stderr"] = None - - try: - stdinFileName = getTempFileName() - stdinFileObj = open(stdinFileName, "w") - stdinFileObj.write(input) - stdinFileObj.close() - stdinFileObj = open(stdinFileName, "r") - - stdoutFileName = getTempFileName() - stdoutFileObj = open(stdoutFileName, "w") - - stderrFileName = getTempFileName() - stderrFileObj = open(stderrFileName, "w") - except IOError, e: - log("Failed to create temporary file for executing command [%s]: %s" % (command, e)) - if output: - return rv - return rv["Status"] - - stdoutContent = None - stderrContent = None - - process = runCommandBG(command, - stdinFileObj=stdinFileObj, - stdoutFileObj=stdoutFileObj, - stderrFileObj=stderrFileObj, - shell=shell, root=root) - if process: - rv['Status'] = process.wait() - rv['Stdout'] = open(stdoutFileName).read() - rv['Stderr'] = open(stderrFileName).read() - - os.remove(stdinFileName) - os.remove(stdoutFileName) - os.remove(stderrFileName) - - log("runCommand(): execution status of command [%s] = [%s]" % (command, rv)) - - if output: - return rv - return rv["Status"] - - -def runCommandFG(command, stdout=False, stderr=False, - shell=False, root=None): - if stdout or stderr: - output = True - else: - output = False - return runCommand(command, output=output, shell=shell, root=root) - - -def IP2Number(ipString): - try: - return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) - except socket.error: - return None - except TypeError: - return None - except struct.error: - return None - - -def Number2IP(number): - try: - return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) - except socket.error: - return None - except AttributeError: - return None - except ValueError: - return None - - -def computeHostName(hostName): - if not hostName: - return False - - hostPrefix = "" - for i in range(len(hostName), 0, -1): - pos = i - 1 - if hostName[pos].isdigit(): - continue - break - hostPrefix = hostName[:pos+1] - try: - hostIndex = int(hostName[pos+1:]) - except ValueError: - hostIndex = 0 - # TODO: Check the availablity of the (server) name - return "%s%s" % (hostPrefix, hostIndex + 1) - - -def daemonize(): - try: - pid = os.fork() - if pid > 0: - # exit first parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - - # do second fork - try: - pid = os.fork() - if pid > 0: - # exit from second parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # redirect standard file descriptors - sys.stdout.flush() - sys.stderr.flush() - si = file("/dev/null", 'r') - so = file("/dev/null", 'a+') - se = file("/dev/null", 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - return True - - -def getDownloadStatus(fileName): - try: - lines = [line for line in open(fileName) - if "saved" in line or "%" in line] - except IOError: - return 0 - if not lines: - return 0 - if "saved" in lines[-1]: - return 100 - return lines[-1].split("%")[0].split()[-1] - - -def getMeminfo(): - """-> dict of data from meminfo (str:int). - Values are in kilobytes. - """ - import re - re_parser = re.compile(r'^(?P\S*):\s*(?P\d*)\s*kB' ) - result = {} - for line in open('/proc/meminfo'): - match = re_parser.match(line) - if not match: - continue # skip lines that don't parse - key, value = match.groups(['key', 'value']) - result[key] = int(value) - result['MemUsed'] = (result['MemTotal'] - result['MemFree']) - return result - - -def getCpuUsage(): - """-> dict of cpuid : (usertime, nicetime, systemtime, idletime) - cpuid "cpu" means the total for all CPUs. - cpuid "cpuN" means the value for CPU N. - """ - wanted_records = [line for line in open('/proc/stat') if - line.startswith('cpu')] - result = {} - for cpuline in wanted_records: - fields = cpuline.split()[:5] - data = map(int, fields[1:]) - result[fields[0]] = tuple(data) - return result - -def _getCpuStatList(): - try: - fp = open("/proc/stat") - cpuStatList = map(float, fp.readline().split()[1:]) - fp.close() - return cpuStatList - except IOError, e: - Utils.log("Failed to open /proc/stat: %s" % str(e)) - return None - -def getCpuUsageAvg(): - st1 = _getCpuStatList() - time.sleep(2) - st2 = _getCpuStatList() - if not (st1 and st2): - return None - delta = [st2[i] - st1[i] for i in range(len(st1))] - cpuPercent = sum(delta[:3]) / delta[3] * 100.0 - return str('%.4f' % cpuPercent) - -def getLoadavg(): - try: - loadavgstr = open('/proc/loadavg', 'r').readline().strip() - except IOError: - syslog.syslog(syslog.LOG_ERR, "failed to find cpu load") - return None - - data = map(float, loadavgstr.split()[1:]) - # returns 1 minute load average - return data[0] - - -def getInfinibandPortStatus(): - - """ Check for availability of infiniband port - and return which port is active in a key pair value - """ - - # Check for existence of infiniband ports - value = os.popen ("ls /sys/class/infiniband").readline().strip() - - if not value: - return None - - portlist = os.popen ("echo /sys/class/infiniband/*/ports/*").readline().split() - - portkeys = {} - - for port in portlist: - value = os.popen ("cat %s/state" % - port.strip()).readline().split(':')[1].strip() - portkeys[port.strip()] = value - - return portkeys - - -def getServerCount(): - try: - return int(open(Globals.SERVER_COUNT_FILE).read().strip()) - except IOError: - log("failed to read file %s" % Globals.SERVER_COUNT_FILE) - return 1 - except ValueError: - log("invalid number format in file %s" % Globals.SERVER_COUNT_FILE) - return 1 - - -def setServerCount(count): - try: - open(Globals.SERVER_COUNT_FILE, "w").write("%s\n" % count) - return True - except IOError: - log("failed to write file %s" % Globals.SERVER_COUNT_FILE) - return False - - -def getInstalledServerCount(): - try: - return int(open(Globals.INSTALLED_SERVER_COUNT_FILE).read().strip()) - except IOError: - log("failed to read file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return 1 - except ValueError: - log("invalid number format in file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return 1 - - -def setInstalledServerCount(count): - try: - open(Globals.INSTALLED_SERVER_COUNT_FILE, "w").write("%s\n" % count) - return True - except IOError: - log("failed to write file %s" % Globals.INSTALLED_SERVER_COUNT_FILE) - return False - - -def getLastInstalledServerIpList(): - ipList = {} - networkDom = Protocol.XDOM() - if not networkDom.parseFile(Globals.GLOBAL_NETWORK_FILE): - log("failed to parse file %s" % Globals.GLOBAL_NETWORK_FILE) - for tagE in networkDom.getElementsByTagRoute("server.interface"): - interfaceDom = Protocol.XDOM() - interfaceDom.setDomObj(tagE) - ipAddress = interfaceDom.getTextByTagRoute("ipaddr") - if ipAddress: - ipList[interfaceDom.getTextByTagRoute("device")] = ipAddress - return ipList - - -def getFreeIpAddress(device=None): - serverCount = getServerCount() - installedServerCount = getInstalledServerCount() - if serverCount == installedServerCount: - return None - - availableServerCount = serverCount - installedServerCount - ipList = getLastInstalledServerIpList() - - if not ipList: - return None - - if device: - if device not in ipList.keys(): - return None - deviceIpAddress = ipList[device] - else: - deviceIpAddress = ipList.values()[0] - ipNumber = IP2Number(deviceIpAddress) - - for i in range((ipNumber + availableServerCount), ipNumber, -1): - ipAddress = Number2IP(i) - if runCommandFG(["ping", "-qnc", "1", ipAddress]) != 0: - return ipAddress - return None - - -def getPasswordHash(userName): - try: - #return spwd.getspnam(userName).sp_pwd - return "Not implimented" - except KeyError: - return None - - -def getTransactionKey(): - try: - tokens = open(Globals.TRANSACTION_KEY_FILE).read().split(',') - except IOError: - return None, None - return tokens - - -def generateSignature(): - #return str(uuid.uuid4()) + ('--%f' % time.time()) - return ('--%f' % time.time()) - - -def getSignature(): - try: - return open(Globals.SIGNATURE_FILE).read().strip() - except IOError: - log(syslog.LOG_ERR, "unable to read signaure from %s file" % Globals.SIGNATURE_FILE) - return False - - -def storeSignature(signature, fileName=Globals.SIGNATURE_FILE): - try: - open(fileName, "w").write(signature + "\n") - except IOError: - log(syslog.LOG_ERR, "unable to write signature %s to %s file" % (signature, fileName)) - return False - return True - - -def isUserExist(userName): - try: - grp.getgrnam(userName).gr_gid - return True - except KeyError: - pass - try: - pwd.getpwnam(userName).pw_uid - return True - except KeyError: - pass - return False - - -def getGsnUserInfo(fileName=Globals.GSN_USER_INFO_FILE): - userInfo = {} - userInfo["UserId"] = None - userInfo["Password"] = None - try: - for line in open(fileName): - line = line.strip() - k = line[:line.index("=")] - v = line[line.index("=") + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "GSN_ID": - userInfo["UserId"] = v - if k.upper() == "GSN_PASSWORD": - userInfo["Password"] = v - except IOError, e: - log("Failed to read file %s: %s" % (fileName, e)) - return userInfo - - -def setGsnUserInfo(userInfo, fileName=Globals.GSN_USER_INFO_FILE): - try: - fp = open(fileName, "w") - fp.write("GSN_ID=%s\n" % userInfo["UserId"]) - fp.write("GSN_PASSWORD=%s\n" % userInfo["Password"]) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (fileName, e)) - return False - - -def getPlatformVersion(fileName=Globals.GLUSTER_VERSION_FILE): - versionInfo = {} - versionInfo["Version"] = None - versionInfo["Update"] = None - try: - lines = open(Globals.GLUSTER_VERSION_FILE).readlines() - for line in open(fileName): - line = line.strip() - k = line[:line.index("=")] - v = line[line.index("=") + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "VERSION": - versionInfo["Version"] = v - if k.upper() == "UPDATE": - versionInfo["Update"] = v - except IOError, e: - log("Failed to read file %s: %s" % (fileName, e)) - return versionInfo - - -def setPlatformVersion(versionInfo, fileName=Globals.GLUSTER_VERSION_FILE): - if isString(versionInfo): - tokens = versionInfo.strip().split(".") - if len(tokens) < 2: - log("Invalid version format %s. Expecting .." % versionInfo) - return False - version = ".".join(tokens[:2]) - update = ".".join(tokens[2:]) - if not update: - update = "0" - else: - version = versionInfo["Version"] - update = versionInfo["Update"] - try: - fp = open(fileName, "w") - fp.write("VERSION=%s\n" % version) - fp.write("UPDATE=%s\n" % update) - fp.close() - return True - except IOError, e: - log("Failed to write file %s: %s" % (fileName, e)) - return False - - -def getGlusterUpdateDom(serverVersion): - errorMessage = "" - updateInfoDom = None - try: - baseUrl = open(Globals.GLUSTER_UPDATE_SITE_FILE).read().strip() - except IOError, e: - log("Failed to read file %s: %s" % (Globals.GLUSTER_UPDATE_SITE_FILE, e)) - errorMessage = "Failed to read update site file" - return updateInfoDom, errorMessage - - try: - url = "%s/%s/%s" % (baseUrl, serverVersion, Globals.GLUSTER_UPDATES_FILE) - connection = urllib.urlopen(url) - if connection.getcode() != 200: - connection.close() - errorMessage = "Error received from server to open URL %s" % url - return updateInfoDom, errorMessage - updateInfoString = connection.read() - connection.close() - except IOError, e: - log("Failed to get update information from URL %s: %s" % (url, e)) - errorMessage = "Error getting update information" - return updateInfoDom, errorMessage - - updateInfoDom = Protocol.XDOM() - if not updateInfoDom.parseString(updateInfoString): - log("XML parse error on update information content [%s]" % updateInfoString) - errorMessage = "Parse error on update information" - updateInfoDom = None - return updateInfoDom, errorMessage - - -def removeFile(fileName, root=False): - if root: - if runCommand("rm %s" % fileName, root=True) == 0: - return True - return False - try: - os.remove(fileName) - return True - except OSError, e: - log("Failed to remove file %s: %s" % (fileName, e)) - return False - - -def isLiveMode(): - return os.path.exists(Globals.LIVE_MODE_FILE) - -def convertKbToMb(kb): - return kb / 1024.0 - - -def getIPIndex(indexFile): - try: - fp = open(indexFile) - line = fp.readline() - fp.close() - index = int(line) - except IOError: - index = 0 - except ValueError: - index = False - return index - -def setIPIndex(index, indexFile): - try: - fp = open(indexFile, "w") - fp.write(str(index)) - fp.close() - except IOError: - return False - return True - -def IP2Number(ipString): - try: - return socket.htonl(struct.unpack("I", socket.inet_aton(ipString))[0]) - except socket.error: - return None - except TypeError: - return None - except struct.error: - return None - -def Number2IP(number): - try: - return socket.inet_ntoa(struct.pack("I", socket.ntohl(number))) - except socket.error: - return None - except AttributeError: - return None - except ValueError: - return None - -def hasEntryFoundInFile(searchString, dnsEntryFileName): - try: - addServerEntryList = open(dnsEntryFileName).read().split() - except IOError: - return None - if searchString in addServerEntryList: - return True - return False - - -def computeIpAddress(ipAddress, startIp, endIp): - startIpNumber = IP2Number(startIp) - endIpNumber = IP2Number(endIp) - if not ipAddress: - return startIp - nextIpNumber = IP2Number(ipAddress) - while True: - nextIpNumber = nextIpNumber + 1 - ipAddress = Number2IP(nextIpNumber) - rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) - if type(rv) == type(True): - return False - if rv != 0: - break - - if nextIpNumber >= startIpNumber and nextIpNumber <= endIpNumber: - return ipAddress - - nextIpNumber = IP2Number(startIp) - while True: - ipAddress = Number2IP(nextIpNumber) - nextIpNumber = nextIpNumber + 1 - rv = runCommandFG(["ping", "-qnc", "1", ipAddress]) - if type(rv) == type(True): - return False - if rv != 0: - break - - if IP2Number(ipAddress) >= startIpNumber and IP2Number(ipAddress) <= endIpNumber: - return ipAddress - return False - - -def setHostNameAndIp(hostName, ipAddress, lastAddServerDetailFile): - try: - fp = open(lastAddServerDetailFile, "w") - fp.write("HOSTNAME=" + hostName + "\n") - fp.write("IPADDRESS=" + ipAddress); - fp.close() - except IOError: - return False - return True - -def getPort(): - try: - fd = open(Globals.PORT_FILE, "r") - portString = fd.readline() - fd.close() - port = int(portString) - except IOError: - port = Globals.DEFAULT_PORT - 2 - except ValueError: - port = Globals.DEFAULT_PORT - 2 - return port - -def setPort(port): - try: - fd = open(Globals.PORT_FILE, "w") - fd.write(str(port)) - fd.close() - except IOError: - return False - return True - -def getServerAgentCredentials(): - try: - lines = open(Globals.SERVERAGENT_AUTH_FILE).readlines() - except IOError: - return None,None - - userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "AGENT_ID": - userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return userName, password - -def getGatewayAgentCredentials(): - try: - lines = open(Globals.GATEWAYAGENT_AUTH_FILE).readlines() - except IOError: - return None - - #userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - #if k.upper() == "AGENT_ID": - # userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return password - -def getWebAgentCredentials(): - try: - lines = open(Globals.WEBAGENT_AUTH_FILE).readlines() - except IOError: - return None,None - - userName = None - password = None - - for l in lines: - if l[-1] == '\n': - l = l[:-1] - k = l[:l.index('=')] - v = l[l.index('=') + 1:] - if v[0] == "'" or v[0] == '"': - v = v[1:] - if v[-1] == "'" or v[-1] == '"': - v = v[:-1] - if k.upper() == "AGENT_ID": - userName = v - if k.upper() == "AGENT_PASSWORD": - password = v - - return userName, password - -def daemonize(): - try: - pid = os.fork() - if pid > 0: - # exit first parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - - # do second fork - try: - pid = os.fork() - if pid > 0: - # exit from second parent - sys.exit(0) - except OSError, e: - #sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - return False - - # redirect standard file descriptors - sys.stdout.flush() - sys.stderr.flush() - si = file("/dev/null", 'r') - so = file("/dev/null", 'a+') - se = file("/dev/null", 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - return True - -def getFreeIpAddress(): - startRange, endRange = getStoragePoolInfo() - if not (startRange and endRange): - return None - - startIpNumber = IP2Number(startRange) - endIpNumber = IP2Number(endRange) - - for ipNumber in range(endIpNumber, startIpNumber, -1): - rv = runCommandFG(["ping", "-qnc", "1", Number2IP(ipNumber)]) - if type(rv) == type(True): - return None - if rv != 0: - return Number2IP(ipNumber) - return None - -def getDhcpServerStatus(): - status = runCommandFG(["sudo", "service", "dnsmasq", " status"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def startDhcpServer(): - status = runCommandFG(["sudo", "service", "dnsmasq", " start"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def stopDhcpServer(): - status = runCommandFG(["sudo", "service", "dnsmasq", " stop"]) - if type(status) == type(True) or 0 != status: - return False - return True - -def getStoragePoolInfo(): - startRange = None - endRange = None - try: - for line in open(Globals.GLUSTER_SERVER_POOL_FILE): - tokens = line.split("=") - if tokens[0] == "STARTRANGE": - startRange = tokens[1].strip() - if tokens[0] == "ENDRANGE": - endRange = tokens[1].strip() - except IOError: - log(syslog.LOG_ERR, "unable to read %s file" % Globals.GLUSTER_SERVER_POOL_FILE) - return startRange, endRange - -def configureDnsmasq(serverIpAddress, dhcpIpAddress): - dnsmasqConfFile = Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf" - serverPortString = "68" - try: - for arg in open("/proc/cmdline").read().strip().split(): - token = arg.split("=") - if token[0] == "dhcp": - serverPortString = token[1] - break - except IOError: - log(syslog.LOG_ERR, "Failed to read /proc/cmdline. Continuing with default port 68") - try: - serverPort = int(serverPortString) - except ValueError: - log(syslog.LOG_ERR, "Invalid dhcp port '%s' in /proc/cmdline. Continuing with default port 68" % serverPortString) - serverPort = 68 - - try: - fp = open(dnsmasqConfFile, "w") - fp.write("no-hosts\n") - #fp.write("addn-hosts=%s\n" % Globals.GLUSTER_DNS_ENTRIES) - fp.write("bind-interfaces\n") - fp.write("except-interface=lo\n") - fp.write("dhcp-range=%s,%s\n" % (dhcpIpAddress, dhcpIpAddress)) - fp.write("dhcp-lease-max=1\n") - #fp.write("dhcp-option=option:router,%s\n" % serverIp) - #fp.write("dhcp-option=option:ntp-server,%s\n" % serverIp) - fp.write("dhcp-alternate-port=%s\n" % serverPort) - fp.write("server=%s\n" % serverIpAddress) - fp.write("dhcp-script=/usr/sbin/server-info\n") - fp.close() - except IOError: - log(syslog.LOG_ERR, "unable to write dnsmasq configuration %s" % dnsmasqConfFile) - return False - status = runCommandFG(["sudo", "cp", "-f", Globals.GLUSTER_CONF_CONF_DIR + "/dnsmasq.conf", Globals.DNSMASQ_CONF_FILE]) - if type(status) == type(True) or 0 != status: - log(syslog.LOG_ERR, "unable to copy dnsmasq configuration to " + Globals.DNSMASQ_CONF_FILE) - return False - return True - -def configureDhcpServer(serverIpAddress, dhcpIpAddress): - return configureDnsmasq(serverIpAddress, dhcpIpAddress) - -def log(priority, message=None): - if type(priority) == type(""): - logPriority = syslog.LOG_INFO - logMessage = priority - else: - logPriority = priority - logMessage = message - if not logMessage: - return - #if Globals.DEBUG: - # sys.stderr.write(logMessage) - else: - syslog.syslog(logPriority, logMessage) - return - - -def stripEmptyLines(content): - ret = "" - for line in content.split("\n"): - if line.strip() != "": - ret += line - return ret - - -def getDeviceFormatStatusFile(device): - return "/var/tmp/format_%s.status" % device.replace('/', '_') - -def getDeviceFormatLockFile(device): - return "/var/lock/format_%s.lock" % device.replace('/', '_') - -def getDeviceFormatOutputFile(device): - return "/var/tmp/format_%s.out" % device.replace('/', '_') diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py b/src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py deleted file mode 100644 index 72164ffb..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/XmlHandler.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import xml -import xml.parsers.expat -import xml.dom.minidom as MDOM -import os -import Globals -import copy -import Utils - -XML_STRING = 0 -XML_FILE = 1 - -class XDOM: - _domObj = None - - def __init__(self): - self._domObj = MDOM.Document() - return - - @classmethod - def getText(self, nodeList): - rc = "" - for node in nodeList: - if node.nodeType == node.TEXT_NODE: - rc = rc + node.data - return rc - - def parseString(self, requestString): - try: - self._domObj = MDOM.parseString(requestString) - except xml.parsers.expat.ExpatError, e: - Utils.log("XML string parse error: %s" % str(e)) - return False - return True - - def parseFile(self, fileName): - try: - self._domObj = MDOM.parse(fileName) - except IOError, e: - Utils.log("error reading file: %s" % str(e)) - return False - except xml.parsers.expat.ExpatError, e: - Utils.log("XML file %s parse error: %s" % (fileName, str(e))) - return False - return True - - def setDomObj(self, dom): - if dom and type(dom) != type([]): - self._domObj = dom - return True - return False - - def createTag(self, tag, text=None): - if not self._domObj: - return None - if tag == None: - return None - - tagE = self._domObj.createElement(str(tag)) - if text: - tagEText = self._domObj.createTextNode(str(text)) - tagE.appendChild(tagEText) - return tagE - - def addTag(self, tag): - if not self._domObj: - return False - if not tag: - return False - - self._domObj.appendChild(tag) - return True - - def createTagRoute(self, tagRoute, text=None): - if not tagRoute: - return False - - tagList = tagRoute.split(".") - tag = None - previousTag = None - for tagName in tagList[:-1]: - newTag = self.createTag(tagName, None) - if not tag: - tag = newTag - previousTag = newTag - continue - previousTag.appendChild(newTag) - previousTag = newTag - - if previousTag: - previousTag.appendChild(self.createTag(tagList[-1], text)) - else: - tag = self.createTag(tagList[-1], text) - return tag - - def appendTagRoute(self, tagRoute, value=None): - if not self._domObj: - return False - if not tagRoute: - return False - - parentTagE = self._domObj - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True - - def setTextByTagRoute(self, tagRoute, tagValue): - if not self._domObj: - return None - - if not tagRoute: - return None - - tagE = self.getElementsByTagRoute(tagRoute) - if not tagE: - return False - - parentTagE = self.getElementsByTagRoute(".".join(tagRoute.split(".")[:-1])) - if not parentTagE: - return False - - parentTagE[0].childNodes.remove(tagE[0]) - parentTagE[0].appendChild(self.createTag(tagRoute.split(".")[-1], tagValue)) - return True - - def getElementsByTagRoute(self, tagRoute): - if not self._domObj: - return None - - if not tagRoute: - return None - - x = None - for tag in tagRoute.split("."): - if x is None: - x = self._domObj.getElementsByTagName(tag) - continue - if x == []: - break - x = x[0].getElementsByTagName(tag) - return x - - def getTextByTagRoute(self, tagRoute): - if not self._domObj: - return None - - x = self.getElementsByTagRoute(tagRoute) - if x: - return self.getText(x[0].childNodes) - return None - - def getElementsByTagName(self, name): - if not self._domObj: - return None - return self._domObj.getElementsByTagName(name) - - def writexml(self, fileName, indent="", addindent="", newl=""): - if not self._domObj: - return None - try: - fp = open(fileName, "w") - self._domObj.writexml(fp, indent, addindent, newl) - fp.close() - return True - except IOError: - return False - - def toString(self, indent=" ", newl="\n", encoding = None): - if not self._domObj: - return None - return self._domObj.toprettyxml(indent, newl, encoding) - - def toxml(self, encoding = None): - if not self._domObj: - return None - return self._domObj.toxml(encoding) - - def toprettyxml(self, indent=" ", newl="\n", encoding = None): - return self.toString(indent, newl, encoding) - - def createResponseTag(self): - responseTag = self._domObj.createElement("response") - return responseTag -##--end of XDOM - -class RequestXml(XDOM): - def __init__(self, requestString, type=None): - if None == requestString: - XDOM.__init__(self) - return - try: - if None == type: - if os.path.isfile(requestString): - self._domObj = MDOM.parse(requestString) - else: - self._domObj = MDOM.parseString(requestString) - elif XML_FILE == type: - self._domObj = MDOM.parse(requestString) - elif XML_STRING == type: - self._domObj = MDOM.parseString(requestString) - except IOError: - XDOM.__init__(self) - except xml.parsers.expat.ExpatError: - XDOM.__init__(self) - -##--end of RequestXML - - -class ResponseXml(XDOM): - _responseTag = None - def __init__(self): - XDOM.__init__(self) - self._responseTag = self.createResponseTag() - self._domObj.appendChild(self._responseTag) - - @classmethod - def errorResponse(self, message): - if not self.responseTag: - return False - self.appendTagRoute("status.code", "-1"); - self.appendTagRoute("status.message", message) - - def append(self, tagName, tagValue=None): - if not self._responseTag: - return False - tag = self.createTag(tagName, tagValue) - if tag: - self._responseTag.appendChild(tag) - return True - return False - - def appendTag(self, tag): - if not tag: - return False - if not self._responseTag: - return False - self._responseTag.appendChild(tag) - return True - - def appendTagRoute(self, tagRoute, value=None): - if not self._responseTag: - return None - if not tagRoute: - return None - - parentTagE = self._responseTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return None - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return None - return newTagE - - def appendTagRouteOld(self, tagRoute, value=None): - if not self._responseTag: - return False - if not tagRoute: - return False - - parentTagE = self._responseTag - - tagNameList = tagRoute.split(".") - newTagRoute = tagNameList.pop(-1) - - for i in range(len(tagNameList), 0, -1): - tagE = self.getElementsByTagRoute(".".join(["response"] + tagNameList[:i])) - if tagE: - parentTagE = tagE[0] - break - newTagRoute = tagNameList[i-1] + "." + newTagRoute - - newTagE = self.createTagRoute(newTagRoute, value) - if not newTagE: - return False - try: - parentTagE.appendChild(newTagE) - except xml.dom.HierarchyRequestErr, e: - Utils.log("error occured. %s" + str(e)) - return False - return True -##--end of ResponseXml - -def test(): - rs = ResponseXml() - rs.appendTagRoute("status.code", "0"); - rs.appendTagRoute("status.message", "SUCCESS") - serverTag = rs.appendTagRoute("server.name", "Server1") - networkInterfaces = rs.appendTagRoute("server.networkInterfaces", None) - networkTag = rs.createTag("networkInterface", None) - networkTag.appendChild(rs.createTag("name", "interface1")) - networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.40")) - networkInterfaces.appendChild(networkTag) - networkTag = rs.createTag("networkInterface", None) - networkTag.appendChild(rs.createTag("name", "interface2")) - networkTag.appendChild(rs.createTag("ipaddress", "192.168.1.41")) - networkInterfaces.appendChild(networkTag) - print rs.toprettyxml() - -#test() diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/add_user_cifs_all.py b/src/com.gluster.storage.management.server/WebContent/scripts/add_user_cifs_all.py deleted file mode 100755 index e4b48658..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/add_user_cifs_all.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Utils - - -defaultUid = 1024000 -cifsUserFile = "/etc/glustermg/.users.cifs" - - -def getLastUid(): - if not os.path.exists(cifsUserFile): - return defaultUid - try: - fp = open(cifsUserFile) - content = fp.read() - fp.close() - except IOError, e: - Utils.log("failed to read file %s: %s" % (cifsUserFile, str(e))) - return False - - lines = content.strip().split() - if not lines: - return defaultUid - return int(lines[-1].split(":")[0]) - - -def setUid(uid, userName): - try: - fp = open(cifsUserFile, "a") - fp.write("%s:%s\n" % (uid, userName)) - fp.close() - return True - except IOError, e: - Utils.log("failed to write file %s: %s" % (cifsUserFile, str(e))) - return False - - -def main(): - if len(sys.argv) < 4: - sys.stderr.write("usage: %s SERVER_FILE USERNAME PASSWORD\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - serverFile = sys.argv[1] - userName = sys.argv[2] - password = sys.argv[3] - - uid = getLastUid() - if not uid: - sys.exit(10) - - uid += 1 - - rv = Utils.runCommand("grun.py %s add_user_cifs.py %s %s %s" % (serverFile, uid, userName, password)) - if rv == 0: - if not setUid(uid, userName): - sys.exit(11) - sys.exit(rv) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/delete_user_cifs_all.py b/src/com.gluster.storage.management.server/WebContent/scripts/delete_user_cifs_all.py deleted file mode 100755 index 38dd8109..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/delete_user_cifs_all.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Utils - - -cifsUserFile = "/etc/glustermg/.users.cifs" - - -def removeUser(userName): - try: - fp = open(cifsUserFile) - content = fp.read() - fp.close() - except IOError, e: - Utils.log("failed to read file %s: %s" % (cifsUserFile, str(e))) - return False - - try: - fp = open(cifsUserFile, "w") - lines = content.strip().split() - for line in lines: - if line.split(":")[1] == userName: - continue - fp.write("%s\n" % line) - fp.close() - except IOError, e: - Utils.log("failed to write file %s: %s" % (cifsUserFile, str(e))) - return False - return True - - -def main(): - if len(sys.argv) < 3: - sys.stderr.write("usage: %s SERVER_LIST USERNAME\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - - serverList = sys.argv[1] - userName = sys.argv[2] - - rv = Utils.runCommand("grun.py %s delete_user_cifs.py %s" % (serverList, userName)) - if rv == 0: - if not removeUser(userName): - sys.exit(10) - sys.exit(rv) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/grun.py b/src/com.gluster.storage.management.server/WebContent/scripts/grun.py deleted file mode 100755 index ae93b7f2..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/grun.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2011 Gluster, Inc. -# This file is part of Gluster Management Gateway. -# - -import os -import sys -import Utils - - -def main(): - sshCommandPrefix = "ssh -q -o BatchMode=yes -o GSSAPIAuthentication=no -o PasswordAuthentication=no -o StrictHostKeyChecking=no".split() - - if len(sys.argv) < 3: - sys.stderr.write("usage: %s SERVER_FILE COMMAND [ARGUMENTS]\n" % os.path.basename(sys.argv[0])) - sys.exit(-1) - serverFile = sys.argv[1] - command = sys.argv[2:] - - try: - fp = open(serverFile) - serverNameList = fp.readlines() - fp.close() - except IOError, e: - Utils.log("Failed to read server file %s: %s\n" % (serverFile, str(e))) - sys.exit(1) - - for serverName in serverNameList: - rv = Utils.runCommand(sshCommandPrefix + [serverName.strip()] + command) - print rv - - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py b/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py deleted file mode 100755 index ac434827..00000000 --- a/src/com.gluster.storage.management.server/WebContent/scripts/multicast-discover-servers.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. -# This file is part of Gluster Storage Platform. -# -# Gluster Storage Platform is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 of -# the License, or (at your option) any later version. -# -# Gluster Storage Platform 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see -# . - -import sys -import socket -import signal -import struct -import syslog -import Globals -import time -import Utils -from XmlHandler import * - -class TimeoutException(Exception): - pass - -def timeoutSignal(signum, frame): - raise TimeoutException, "Timed out" - -def serverDiscoveryRequest(multiCastGroup, port): - servers = [] - # Sending request to all the servers - socketSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketSend.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) - socketSend.sendto("ServerDiscovery", (multiCastGroup, port)) - - # Waiting for the response - socketReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) - socketReceive.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - socketReceive.bind(('', port)) - mreq = struct.pack("4sl", socket.inet_aton(multiCastGroup), socket.INADDR_ANY) - - socketReceive.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - sendtime = time.time() - socketSend.sendto("ServerDiscovery" % (sendtime), (multiCastGroup, port)) - - try: - while True: - response = socketReceive.recvfrom(200) - if not response: - continue - dom = XDOM() - dom.parseString(response[0]) - if not dom: - continue - if dom.getTextByTagRoute("request.name"): - continue - responsetime = dom.getTextByTagRoute("response.time") - servername = dom.getTextByTagRoute("response.servername") - if responsetime == str(sendtime): - servers.append(servername) - signal.signal(signal.SIGALRM, timeoutSignal) - signal.alarm(3) - except TimeoutException: - return servers - return None - -def main(): - syslog.openlog("discovery server request") - servers = serverDiscoveryRequest(Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT) - if not servers: - Utils.log(syslog.LOG_ERR, "Failed to discover new servers") - sys.exit(-1) - - servers = set(servers) - try: - for server in servers: - print server - except IOError: - Utils.log(syslog.LOG_ERR, "Unable to open file %s" % Globals.DISCOVERED_SERVER_LIST_FILENAME) - sys.exit(-1) - sys.exit(0) - -if __name__ == "__main__": - main() diff --git a/src/com.gluster.storage.management.server/WebContent/ssl/gmg-ssl.keystore b/src/com.gluster.storage.management.server/WebContent/ssl/gmg-ssl.keystore deleted file mode 100644 index 2efe19b0..00000000 Binary files a/src/com.gluster.storage.management.server/WebContent/ssl/gmg-ssl.keystore and /dev/null differ diff --git a/src/com.gluster.storage.management.server/buckminster.cspex b/src/com.gluster.storage.management.server/buckminster.cspex deleted file mode 100644 index 31eb9d67..00000000 --- a/src/com.gluster.storage.management.server/buckminster.cspex +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/build/glusterserver.ant b/src/com.gluster.storage.management.server/build/glusterserver.ant deleted file mode 100644 index 68a5bc08..00000000 --- a/src/com.gluster.storage.management.server/build/glusterserver.ant +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - -------------------------------------------------- - compile - Compile - archive - Generate WAR file - -------------------------------------------------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com.gluster.storage.management.server/src/META-INF/persistence.xml b/src/com.gluster.storage.management.server/src/META-INF/persistence.xml deleted file mode 100644 index 36b252ea..00000000 --- a/src/com.gluster.storage.management.server/src/META-INF/persistence.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java deleted file mode 100644 index 1f577c89..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/constants/VolumeOptionsDefaults.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * DefaultVolumeOptions.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.gateway.constants; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.model.VolumeOptionInfo; - -@Component -public class VolumeOptionsDefaults { - public List options; - - public VolumeOptionsDefaults() { - } - - /** - * @return list of volume option information objects - */ - public List getDefaults() { - return getVolumeOptionsInfo(); - } - - /** - * Fetches the list of all volume options with their information from GlusterFS and returns the same - * - * @return List of volume option information objects - */ - private List getVolumeOptionsInfo() { - List volumeOptionsInfo = new ArrayList(); - - volumeOptionsInfo - .add(new VolumeOptionInfo( - "cluster.stripe-block-size", - "This could be used in case of a stripe setup. Specifies the size of the stripe unit that will read from or written to the striped servers. " - + CoreConstants.NEWLINE - + "Optionally different stripe unit sizes can be specified for different fies, with the following pattern . ", - "*:128KB")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "cluster.self-heal-window-size", - "Specifies the number of maximum number blocks per file for which self-heal process would be applied simultaneously.", - "16")); - volumeOptionsInfo.add(new VolumeOptionInfo("cluster.data-self-heal-algorithm", - "cluster.data-self-heal-algorithm", "auto")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "network.frame-timeout", - "The time frame after which the operation has to be declared as dead, if the server does not respond for a particular operation.", - "1800")); - volumeOptionsInfo.add(new VolumeOptionInfo("network.ping-timeout", - "The time duration for which the client waits to check if the server is responsive.", "42")); - volumeOptionsInfo.add(new VolumeOptionInfo("auth.allow", - "'IP addresses/Host name' of the clients which should be allowed to access the the volume.", "*")); - volumeOptionsInfo.add(new VolumeOptionInfo("auth.reject", - "'IP addresses/Host name' of the clients which should be denied to access the volume.", "NONE")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "performance.cache-refresh-timeout", - "The cached data for a file will be retained till 'cache-refresh-timeout' seconds, after which data re-validation is performed.", - "1")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-size", "Size of the read cache.", "32MB")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.write-behind-window-size", - "Size of the per-file write-behind buffer.", "1MB")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-max-file-size", - "performance.cache-max-file-size", "-1")); - volumeOptionsInfo.add(new VolumeOptionInfo("performance.cache-min-file-size", - "performance.cache-min-file-size", "0")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "performance.io-thread-count", - " Number of threads in the thread-pool in the bricks to improve the concurrency in I/O s of server side.", - "16")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "diagnostics.latency-measurement", - "Statistics related to the latency of each operation would be tracked inside GlusterFS data-structures.", - "off")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.dump-fd-stats", - "Statistics related to file-operations would be tracked inside GlusterFS data-structures.", "off")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.brick-log-level", - "Changes the log-level of the bricks (servers).", "INFO")); - volumeOptionsInfo.add(new VolumeOptionInfo("diagnostics.client-log-level", - "Changes the log-level of the clients.", "INFO")); - volumeOptionsInfo.add(new VolumeOptionInfo("nfs.enable-ino32", - "Use this option from the CLI to make Gluster NFS return 32-bit inode numbers instead of 64-bit.", - "off")); - volumeOptionsInfo - .add(new VolumeOptionInfo( - "nfs.mem-factor", - "This option specifies a multiple that determines the total amount of memory used. Increases this increases the performance of NFS.", - "15")); - volumeOptionsInfo.add(new VolumeOptionInfo("transport.keepalive", "transport.keepalive", "on")); - - return volumeOptionsInfo; - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java deleted file mode 100644 index 3e5ea01a..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ClusterInfo.java +++ /dev/null @@ -1,79 +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.gateway.data; - -import java.util.ArrayList; -import java.util.List; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; - -import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.tool.hbm2ddl.SchemaExport; - -@Entity(name="cluster_info") -public class ClusterInfo { - @Id - @GeneratedValue - private Integer id; - - private String name; - - @OneToMany(mappedBy="cluster") - private List servers = new ArrayList(); - - public void setId(Integer id) { - this.id = id; - } - - public Integer getId() { - return id; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setServers(List servers) { - this.servers = servers; - } - - public List getServers() { - return servers; - } - - public void addServer(ServerInfo server) { - servers.add(server); - } - - public static void main(String args[]) { - AnnotationConfiguration config = new AnnotationConfiguration(); - config.addAnnotatedClass(ClusterInfo.class); - config.addAnnotatedClass(ServerInfo.class); - config.configure(); - new SchemaExport(config).create(true, true); - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java deleted file mode 100644 index 0802fe93..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/GlusterDataSource.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * GlusterDataSource.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.gateway.data; - -import javax.servlet.ServletContext; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.stereotype.Component; - -@Component -public class GlusterDataSource extends DriverManagerDataSource { - @Autowired - ServletContext servletContext; - - public GlusterDataSource() { - setDriverClassName(org.apache.derby.jdbc.EmbeddedDriver.class.getName()); - - setUsername("gluster"); - // TODO: change to a stronger (encrypted) password - setPassword("gluster"); - } - - public DriverManagerDataSource getDataSource() { - // Database directory = work/data relative to context root - setUrl("jdbc:derby:" + servletContext.getRealPath("data") + ";create=true"); - - return this; - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java deleted file mode 100644 index eb7d6514..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/PersistenceDao.java +++ /dev/null @@ -1,113 +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.gateway.data; - -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; -import javax.persistence.EntityTransaction; -import javax.persistence.PersistenceUnit; -import javax.persistence.Query; - -/** - * - */ -public class PersistenceDao { - private Class type; - - private EntityManager entityManager; - - @PersistenceUnit - private EntityManagerFactory entityManagerFactory; - - public PersistenceDao(Class type) { - this.type = type; - } - - public EntityTransaction startTransaction() { - EntityTransaction txn = getEntityManager().getTransaction(); - txn.begin(); - return txn; - } - - private synchronized EntityManager getEntityManager() { - if (entityManager == null) { - entityManager = entityManagerFactory.createEntityManager(); - } - return entityManager; - } - - public Object getSingleResult(String query) { - return getEntityManager().createQuery(query).getSingleResult(); - } - - public Object getSingleResult(String queryString, String... params) { - return createQuery(queryString, params).getSingleResult(); - } - - private Query createQuery(String queryString, String... params) { - Query query = getEntityManager().createQuery(queryString); - for (int i = 0; i < params.length; i++) { - query.setParameter(i + 1, params[i]); - } - return query; - } - - public Object getSingleResultFromSQL(String sqlQuery) { - return getEntityManager().createNativeQuery(sqlQuery).getSingleResult(); - } - - @SuppressWarnings("rawtypes") - public List findBySQL(String sqlQuery) { - return getEntityManager().createNativeQuery(sqlQuery).getResultList(); - } - - public T findById(int id) { - return getEntityManager().find(type, id); - } - - @SuppressWarnings("unchecked") - public List findAll() { - return getEntityManager().createQuery("select t from " + type.getName() + " t").getResultList(); - } - - @SuppressWarnings("unchecked") - public List findBy(String whereClause) { - return getEntityManager().createQuery("select t from " + type.getName() + " t where " + whereClause) - .getResultList(); - } - - @SuppressWarnings("unchecked") - public List findBy(String whereClause, String... params) { - return createQuery("select t from " + type.getName() + " t where " + whereClause, params).getResultList(); - } - - public void save(Object obj) { - getEntityManager().persist(obj); - } - - public T update(T obj) { - return getEntityManager().merge(obj); - } - - public void delete(Object obj) { - getEntityManager().remove(obj); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java deleted file mode 100644 index a3f8c920..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/data/ServerInfo.java +++ /dev/null @@ -1,72 +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.gateway.data; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; - -/** - * - */ -@Entity(name="server_info") -public class ServerInfo { - @Id - @GeneratedValue - private Integer id; - - private String name; - - @ManyToOne - @JoinColumn(name="cluster_id") - private ClusterInfo cluster; - - public ServerInfo() { - } - - public ServerInfo(String name) { - setName(name); - } - - public void setId(Integer id) { - this.id = id; - } - - public Integer getId() { - return id; - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setCluster(ClusterInfo cluster) { - this.cluster = cluster; - } - - public ClusterInfo getCluster() { - return cluster; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java deleted file mode 100644 index 31810123..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuditFilter.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * - */ -package com.gluster.storage.management.gateway.filters; - -import com.sun.jersey.spi.container.ContainerRequest; -import com.sun.jersey.spi.container.ContainerRequestFilter; -import com.sun.jersey.spi.container.ContainerResponse; -import com.sun.jersey.spi.container.ContainerResponseFilter; -import com.sun.jersey.spi.container.ResourceFilter; - -/** - * Resource filter for maintaining audit trail of resource access - */ -public class AuditFilter implements ResourceFilter, ContainerRequestFilter, ContainerResponseFilter { - - @Override - public ContainerRequestFilter getRequestFilter() { - return this; - } - - @Override - public ContainerResponseFilter getResponseFilter() { - return this; - } - - @Override - public ContainerRequest filter(ContainerRequest req) { - System.out.println("REQUEST: [" + req.getMethod() + "][" + req.getPath() + "]"); - return req; - } - - @Override - public ContainerResponse filter(ContainerRequest req, ContainerResponse response) { - System.out.println("RESPONSE: [" + req.getMethod() + "][" + req.getPath() + "]"); - return response; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java deleted file mode 100644 index 73a1085e..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/AuthenticationFailureFilter.java +++ /dev/null @@ -1,105 +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.gateway.filters; - -import java.io.CharArrayWriter; -import java.io.IOException; -import java.io.PrintWriter; - -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import javax.ws.rs.core.Response; - -/** - * @author root - * - */ -public class AuthenticationFailureFilter implements Filter { - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#destroy() - */ - @Override - public void destroy() { - // TODO Auto-generated method stub - - } - - public class CharResponseWrapper extends HttpServletResponseWrapper { - private CharArrayWriter output; - - public String toString() { - return output.toString(); - } - - public CharResponseWrapper(HttpServletResponse response) { - super(response); - output = new CharArrayWriter(); - } - - public PrintWriter getWriter() { - return new PrintWriter(output); - } - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, - * javax.servlet.FilterChain) - */ - @Override - public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, - ServletException { - HttpServletRequest request = (HttpServletRequest) req; - if (request.getRequestURI().contains("download")) { - chain.doFilter(req, res); - return; - } - - CharResponseWrapper wrapper = new CharResponseWrapper((HttpServletResponse) res); - chain.doFilter(req, wrapper); - - if(wrapper.getStatus() == Response.Status.UNAUTHORIZED.ordinal()) { - PrintWriter out = res.getWriter(); - out.println("1Authentication Failed!"); - } - } - - /* - * (non-Javadoc) - * - * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) - */ - @Override - public void init(FilterConfig arg0) throws ServletException { - // TODO Auto-generated method stub - - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java deleted file mode 100644 index 1c480f3f..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/filters/GlusterResourceFilterFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - */ -package com.gluster.storage.management.gateway.filters; - -import java.util.ArrayList; -import java.util.List; - -import com.sun.jersey.api.model.AbstractMethod; -import com.sun.jersey.spi.container.ResourceFilter; -import com.sun.jersey.spi.container.ResourceFilterFactory; - -/** - * Gluster resource filter factory. As of now, this creates only one filter - the audit filter {@code AuditFilter} - */ -public class GlusterResourceFilterFactory implements ResourceFilterFactory { - - public GlusterResourceFilterFactory() { - } - - /* (non-Javadoc) - * @see com.sun.jersey.spi.container.ResourceFilterFactory#create(com.sun.jersey.api.model.AbstractMethod) - */ - @Override - public List create(AbstractMethod arg0) { - List filters = new ArrayList(); - filters.add(new AuditFilter()); - - return filters; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java deleted file mode 100644 index 9fc4fceb..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/AbstractResource.java +++ /dev/null @@ -1,177 +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.gateway.resources.v1_0; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; - -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.StreamingOutput; -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 - * 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(); - } - - protected StreamingOutput createStreamingOutput(final byte[] data) { - return new StreamingOutput() { - @Override - public void write(OutputStream output) throws IOException { - output.write(data); - } - }; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java deleted file mode 100644 index d0da6696..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/ClustersResource.java +++ /dev/null @@ -1,126 +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.gateway.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.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.response.ClusterNameListResponse; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.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; - private static final Logger logger = Logger.getLogger(ClustersResource.class); - - @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()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); - } - - clusterService.createCluster(clusterName); - return createdResponse(clusterName); - } - - @PUT - public Response registerCluster(@FormParam(FORM_PARAM_CLUSTER_NAME) String clusterName, - @FormParam(FORM_PARAM_SERVER_NAME) String knownServer) { - if(clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - if(knownServer == null || knownServer.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_SERVER_NAME + "] is missing in request!"); - } - - if(clusterService.getCluster(clusterName) != null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] already exists!"); - } - - ClusterInfo mappedCluster = clusterService.getClusterForServer(knownServer); - if(mappedCluster != null) { - throw new GlusterValidationException("Server [" + knownServer + "] is already present in cluster [" - + mappedCluster.getName() + "]!"); - } - - clusterService.registerCluster(clusterName, knownServer); - return noContentResponse(clusterName); - } - - @Path("{" + PATH_PARAM_CLUSTER_NAME + "}") - @DELETE - public Response unregisterCluster(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName) { - if(clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Parameter [" + FORM_PARAM_CLUSTER_NAME + "] is missing in request!"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if(cluster == null) { - throw new GlusterValidationException("Cluster [" + clusterName + "] does not exist!"); - } - - clusterService.unregisterCluster(cluster); - return noContentResponse(); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java deleted file mode 100644 index 2d07bd24..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/DiscoveredServersResource.java +++ /dev/null @@ -1,150 +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.gateway.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.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.ServerUtil; -import com.sun.jersey.api.core.InjectParam; -import com.sun.jersey.spi.resource.Singleton; - -@Component -@Singleton -@Path(RESOURCE_PATH_DISCOVERED_SERVERS) -public class DiscoveredServersResource extends AbstractResource { - @InjectParam - protected ServerUtil serverUtil; - - @InjectParam - protected GlusterUtil glusterUtil; - - 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/gateway/resources/v1_0/GenericExceptionMapper.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java deleted file mode 100644 index 3a316c0c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GenericExceptionMapper.java +++ /dev/null @@ -1,54 +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.gateway.resources.v1_0; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.ResponseBuilder; -import javax.ws.rs.ext.ExceptionMapper; -import javax.ws.rs.ext.Provider; - -import com.gluster.storage.management.core.exceptions.GlusterValidationException; - -@Provider -public class GenericExceptionMapper implements ExceptionMapper { - - /* (non-Javadoc) - * @see javax.ws.rs.ext.ExceptionMapper#toResponse(java.lang.Throwable) - */ - @Override - public Response toResponse(Exception exception) { - ResponseBuilder builder; - if (exception instanceof GlusterValidationException) { - builder = Response.status(Response.Status.BAD_REQUEST); - } else { - builder = Response.status(Response.Status.INTERNAL_SERVER_ERROR); - } - - String errMsg = exception.getMessage(); - if(errMsg == null) { - errMsg = "Following exception occurred : " + exception.getClass().getName(); - StackTraceElement[] stackTrace = exception.getStackTrace(); - if(stackTrace.length > 0) { - errMsg += " at [" + stackTrace[0].getClassName() + "][" + stackTrace[0].getLineNumber() + "]"; - } - } - return builder.entity(errMsg).type(MediaType.TEXT_PLAIN).build(); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java deleted file mode 100644 index e6e4f9d6..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/GlusterServersResource.java +++ /dev/null @@ -1,487 +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.gateway.resources.v1_0; - -import static com.gluster.storage.management.core.constants.RESTConstants.FORM_PARAM_FSTYPE; -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.QUERY_PARAM_DETAILS; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_INTERFACE; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_PERIOD; -import static com.gluster.storage.management.core.constants.RESTConstants.QUERY_PARAM_TYPE; -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_STATISTICS; -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_TASKS; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_CPU; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_MEMORY; -import static com.gluster.storage.management.core.constants.RESTConstants.STATISTICS_TYPE_NETWORK; - -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.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.constants.RESTConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.response.GlusterServerListResponse; -import com.gluster.storage.management.core.response.ServerNameListResponse; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.data.ServerInfo; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.services.GlusterServerService; -import com.gluster.storage.management.gateway.tasks.InitializeDiskTask; -import com.gluster.storage.management.gateway.utils.CpuStatsFactory; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.MemoryStatsFactory; -import com.gluster.storage.management.gateway.utils.NetworkStatsFactory; -import com.gluster.storage.management.gateway.utils.ServerUtil; -import com.gluster.storage.management.gateway.utils.SshUtil; -import com.gluster.storage.management.gateway.utils.StatsFactory; -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 AbstractResource { - - public static final String HOSTNAMETAG = "hostname:"; - - @InjectParam - private DiscoveredServersResource discoveredServersResource; - - @InjectParam - private TasksResource taskResource; - - @InjectParam - private ClusterService clusterService; - - @InjectParam - private SshUtil sshUtil; - - @InjectParam - private CpuStatsFactory cpuStatsFactory; - - @InjectParam - private MemoryStatsFactory memoryStatsFactory; - - @InjectParam - private NetworkStatsFactory networkStatsFactory; - - @InjectParam - private ServerUtil serverUtil; - - @InjectParam - private GlusterUtil glusterUtil; - - @InjectParam - private GlusterServerService glusterServerService; - - @GET - @Produces(MediaType.APPLICATION_JSON) - public Response getGlusterServersJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getGlusterServers(clusterName, MediaType.APPLICATION_JSON, details); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - public Response getGlusterServersXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_DETAILS) Boolean details) { - return getGlusterServers(clusterName, MediaType.APPLICATION_XML, details); - } - - private Response getGlusterServers(String clusterName, String mediaType, Boolean fetchDetails) { - if(fetchDetails == null) { - // by default, fetch the server details - fetchDetails = true; - } - - 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); - } - - try { - glusterServers = glusterServerService.getGlusterServers(clusterName, fetchDetails); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - - if(fetchDetails) { - return okResponse(new GlusterServerListResponse(glusterServers), mediaType); - } else { - // no details to be fetched. Return list of server names. - return okResponse(new ServerNameListResponse(getServerNames(glusterServers)), mediaType); - } - } - - private List getServerNames(List glusterServers) { - List serverNames = new ArrayList(); - for(GlusterServer server : glusterServers) { - serverNames.add(server.getName()); - } - return serverNames; - } - - @GET - @Path("{" + PATH_PARAM_SERVER_NAME + "}") - @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("{" + PATH_PARAM_SERVER_NAME + "}") - @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(glusterServerService.getGlusterServer(clusterName, serverName, true), mediaType); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - 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."); - } - - String hostName = serverUtil.fetchHostName(serverName); - 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, hostName); - } 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()); - } - } - clusterService.unmapServerFromCluster(clusterName, serverName); - - 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); - } - - // 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, - @FormParam(FORM_PARAM_FSTYPE) String fsType) { - - 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!"); - } - - if (fsType == null || fsType.isEmpty()) { - return badRequestResponse("Parameter [" + FORM_PARAM_FSTYPE + "] is missing in request!"); - } - - InitializeDiskTask initializeTask = new InitializeDiskTask(clusterService, clusterName, serverName, diskName, fsType); - try { - initializeTask.start(); - // Check the initialize disk status - TaskStatus taskStatus = initializeTask.checkStatus(); - initializeTask.getTaskInfo().setStatus(taskStatus); - taskResource.addTask(initializeTask); - - return acceptedResponse(RESTConstants.RESOURCE_PATH_CLUSTERS + "/" + clusterName + "/" + RESOURCE_TASKS + "/" - + initializeTask.getId()); - } catch (Exception e) { - return errorResponse(e.getMessage()); - } - } - - @GET - @Produces(MediaType.APPLICATION_XML) - @Path(RESOURCE_STATISTICS) - public Response getAggregatedPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { - return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_XML); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path(RESOURCE_STATISTICS) - public Response getAggregaredPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period) { - return getAggregaredPerformanceData(clusterName, type, period, MediaType.APPLICATION_JSON); - } - - @GET - @Produces(MediaType.APPLICATION_XML) - @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataXML(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, - @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { - return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_XML); - } - - @GET - @Produces(MediaType.APPLICATION_JSON) - @Path("{" + PATH_PARAM_SERVER_NAME + "}/" + RESOURCE_STATISTICS) - public Response getPerformanceDataJSON(@PathParam(PATH_PARAM_CLUSTER_NAME) String clusterName, @PathParam(PATH_PARAM_SERVER_NAME) String serverName, - @QueryParam(QUERY_PARAM_TYPE) String type, @QueryParam(QUERY_PARAM_PERIOD) String period, - @QueryParam(QUERY_PARAM_INTERFACE) String networkInterface) { - return getPerformanceData(clusterName, serverName, type, period, networkInterface, MediaType.APPLICATION_JSON); - } - - private Response getAggregaredPerformanceData(String clusterName, String type, String period, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (type == null || type.isEmpty()) { - throw new GlusterValidationException("Statistics type name must not be empty!"); - } - - if (period == null || period.isEmpty()) { - throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); - } - - ClusterInfo cluster = clusterService.getCluster(clusterName); - if (cluster == null) { - return notFoundResponse("Cluster [" + clusterName + "] not found!"); - } - - if (cluster.getServers().isEmpty()) { - // cluster is empty. return empty stats. - return okResponse(new ServerStats(), mediaType); - } - - List serverNames = getServerNames(glusterServerService.getGlusterServers(clusterName, false)); - return okResponse(getStatsFactory(type).fetchAggregatedStats(serverNames, period), mediaType); - } - - private Response getPerformanceData(String clusterName, String serverName, String type, String period, String networkInterface, String mediaType) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterValidationException("Server name must not be empty!"); - } - - if (type == null || type.isEmpty()) { - throw new GlusterValidationException("Statistics type name must not be empty!"); - } - - if (period == null || period.isEmpty()) { - throw new GlusterValidationException("Statistics period name must not be empty! Valid values are 1d/1w/1m/1y"); - } - - return okResponse(getStatsFactory(type).fetchStats(serverName, period, networkInterface), mediaType); - } - - private StatsFactory getStatsFactory(String type) { - if(type.equals(STATISTICS_TYPE_CPU)) { - return cpuStatsFactory; - } else if(type.equals(STATISTICS_TYPE_MEMORY)) { - return memoryStatsFactory; - } else if(type.equals(STATISTICS_TYPE_NETWORK)) { - return networkStatsFactory; - } else { - throw new GlusterValidationException("Invalid server statistics type [" + type + "]. Valid values are [" - + STATISTICS_TYPE_CPU + ", " + STATISTICS_TYPE_NETWORK + ", " + STATISTICS_TYPE_MEMORY + "]"); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java deleted file mode 100644 index 34dad497..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/KeysResource.java +++ /dev/null @@ -1,153 +0,0 @@ -/** - * KeysResource.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.gateway.resources.v1_0; - -import static com.gluster.storage.management.core.constants.RESTConstants.RESOURCE_PATH_KEYS; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -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.utils.FileUtil; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.core.utils.ProcessUtil; -import com.gluster.storage.management.gateway.utils.SshUtil; -import com.sun.jersey.multipart.FormDataParam; - -@Path(RESOURCE_PATH_KEYS) -public class KeysResource extends AbstractResource { - private static final Logger logger = Logger.getLogger(KeysResource.class); - private ProcessUtil processUtil = new ProcessUtil(); - - @GET - @Produces(MediaType.APPLICATION_OCTET_STREAM) - public Response exportSshkeys() { - File archiveFile = new File(createSskKeyZipFile()); - byte[] data = FileUtil.readFileAsByteArray(archiveFile); - archiveFile.delete(); - return streamingOutputResponse(createStreamingOutput(data)); - } - - private String createSskKeyZipFile() { - String targetDir = System.getProperty("java.io.tmpdir"); - String zipFile = targetDir + "ssh-keys.tar"; - String sourcePemFile = SshUtil.PRIVATE_KEY_FILE.getAbsolutePath(); - String sourcePubKeyFile = SshUtil.PUBLIC_KEY_FILE.getAbsolutePath(); - String targetPemFile = targetDir + File.separator + SshUtil.PRIVATE_KEY_FILE.getName(); - String targetPubKeyFile = targetDir + File.separator + SshUtil.PUBLIC_KEY_FILE.getName(); - - if (!SshUtil.PRIVATE_KEY_FILE.isFile()) { - throw new GlusterRuntimeException("No private key file [" + SshUtil.PRIVATE_KEY_FILE.getName() + "] found!" ); - } - - if (!SshUtil.PUBLIC_KEY_FILE.isFile()) { - throw new GlusterRuntimeException("No public key file [" + SshUtil.PUBLIC_KEY_FILE.getName() + "] found!" ); - } - - // Copy keys to temp folder - ProcessResult result = processUtil.executeCommand("cp", sourcePemFile, targetPemFile); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); - } - result = processUtil.executeCommand("cp", sourcePubKeyFile, targetPubKeyFile); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to copy key files! [" + result.getOutput() + "]"); - } - - // To compress the key files - result = processUtil.executeCommand("tar", "cvf", zipFile, "-C", "/tmp", SshUtil.PRIVATE_KEY_FILE.getName(), - SshUtil.PUBLIC_KEY_FILE.getName()); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Failed to compress key files! [" + result.getOutput() + "]"); - } - - // To remove the copied key files - try { - processUtil.executeCommand("rm", "-f", targetPemFile, targetPubKeyFile); // Ignore the errors if any - } catch (Exception e) { - logger.warn(e.toString()); - } - return zipFile; - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - public Response importSshKeys(@FormDataParam("file") InputStream uploadedInputStream) { - File uploadedFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "keys.tar"); - String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); - - writeToFile(uploadedInputStream, uploadedFile.getAbsolutePath()); - - // To backup existing SSH pem and public keys, if exist. - if (SshUtil.PRIVATE_KEY_FILE.isFile()) { - if (!SshUtil.PRIVATE_KEY_FILE.renameTo(new File(SshUtil.PRIVATE_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { - throw new GlusterRuntimeException("Unable to backup pem key!"); - } - } - - if (SshUtil.PUBLIC_KEY_FILE.isFile()) { - if (!SshUtil.PUBLIC_KEY_FILE - .renameTo(new File(SshUtil.PUBLIC_KEY_FILE.getAbsolutePath() + "-" + timestamp))) { - throw new GlusterRuntimeException("Unable to backup public key!"); - } - } - // Extract SSH pem and public key files. - ProcessResult output = processUtil.executeCommand("tar", "xvf", uploadedFile.getName(), "-C", - SshUtil.SSH_AUTHORIZED_KEYS_DIR_LOCAL); - uploadedFile.delete(); - if (!output.isSuccess()) { - throw new GlusterRuntimeException(output.getOutput()); - } - return createdResponse("SSH Key imported successfully"); - } - - // save uploaded file to the file (with path) - private void writeToFile(InputStream inputStream, String toFile) { - try { - int read = 0; - byte[] bytes = new byte[1024]; - - OutputStream out = new FileOutputStream(new File(toFile)); - while ((read = inputStream.read(bytes)) != -1) { - out.write(bytes, 0, read); - } - out.flush(); - out.close(); - } catch (IOException e) { - throw new GlusterRuntimeException(e.getMessage()); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java deleted file mode 100644 index e5874f4b..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/TasksResource.java +++ /dev/null @@ -1,194 +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.gateway.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 org.springframework.stereotype.Component; - -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.Status; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.response.TaskInfoListResponse; -import com.gluster.storage.management.gateway.tasks.Task; -import com.sun.jersey.spi.resource.Singleton; - -@Path(RESOURCE_PATH_CLUSTERS + "/{" + PATH_PARAM_CLUSTER_NAME + "}/" + RESOURCE_TASKS) -@Singleton -@Component -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; - } - - public List getAllTasks() { - List tasks = new ArrayList(); - for (Map.Entry entry : tasksMap.entrySet()) { - checkTaskStatus(entry.getKey()); - tasks.add( (Task) entry.getValue()); - } - return tasks; - } - - @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); - // No status check required if the task already complete or failure - if (task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_FAILURE - || task.getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { - return task; - } - 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(); - clearTask(taskId, taskOperation); // Stop and remove from the task list - } 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 clearTask(@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/gateway/resources/v1_0/UsersResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java deleted file mode 100644 index 4b2701f2..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/UsersResource.java +++ /dev/null @@ -1,91 +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.gateway.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/gateway/resources/v1_0/VolumesResource.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java deleted file mode 100644 index 45df1ae7..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/resources/v1_0/VolumesResource.java +++ /dev/null @@ -1,989 +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.gateway.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.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.core.MediaType; -import javax.ws.rs.core.Response; - -import org.apache.log4j.Logger; - -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.exceptions.GlusterValidationException; -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.gateway.constants.VolumeOptionsDefaults; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.tasks.MigrateBrickTask; -import com.gluster.storage.management.gateway.tasks.RebalanceVolumeTask; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.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"; - private static final Logger logger = Logger.getLogger(VolumesResource.class); - - @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 void performOperation(String volumeName, String operation, GlusterServer onlineServer) { - if (operation.equals(TASK_START)) { - glusterUtil.startVolume(volumeName, onlineServer.getName()); - } else if (operation.equals(TASK_STOP)) { - glusterUtil.stopVolume(volumeName, onlineServer.getName()); - } else { - throw new GlusterValidationException("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) { - Status status; - try { - status = 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 + "]"); - } - status = glusterUtil.removeBricks(volumeName, brickList, onlineServer.getName()); - } - if (!status.isSuccess()) { - throw new GlusterRuntimeException(status.toString()); - } - } - - @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.executeScriptOnServer(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.executeScriptOnServer(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.executeScriptOnServer(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); - File archiveFile = new File(downloadLogs(volume)); - byte[] data = FileUtil.readFileAsByteArray(archiveFile); - archiveFile.delete(); - return streamingOutputResponse(createStreamingOutput(data)); - } catch (Exception e) { - logger.error("Volume [" + volumeName + "] doesn't exist in cluster [" + clusterName + "]! [" - + e.getStackTrace() + "]"); - throw (GlusterRuntimeException) e; - } - } - - - 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 getLayout(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 layout; - } - - private String rebalanceStart(String clusterName, String volumeName, Boolean isFixLayout, Boolean isMigrateData, - Boolean isForcedDataMigrate) { - RebalanceVolumeTask rebalanceTask = new RebalanceVolumeTask(clusterService, clusterName, volumeName, getLayout( - isFixLayout, isMigrateData, isForcedDataMigrate)); - 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(); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java deleted file mode 100644 index e806051c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/GlusterUserDetailsService.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * GlusterUserDetailsService.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.gateway.security; - -import org.springframework.security.core.userdetails.UserDetailsService; - -/** - * - */ -public interface GlusterUserDetailsService extends UserDetailsService { - void changePassword(String username, String password); -} - diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java deleted file mode 100644 index bdc3b19e..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/security/UserAuthDao.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * UserAuthDao.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.gateway.security; - -import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl; - -/** - * @author root - * - */ -public class UserAuthDao extends JdbcDaoImpl implements GlusterUserDetailsService { - - /* - * (non-Javadoc) - * - * @see com.gluster.storage.management.gateway.security.GlusterUserDetailsService#changePassword(java.lang.String, - * java.lang.String) - */ - @Override - public void changePassword(String username, String password) { - getJdbcTemplate().update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?", password, username); - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java deleted file mode 100644 index e01c5096..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/ClusterService.java +++ /dev/null @@ -1,269 +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.gateway.services; - -import java.util.ArrayList; -import java.util.List; - -import javax.persistence.EntityTransaction; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.core.utils.LRUCache; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.data.PersistenceDao; -import com.gluster.storage.management.gateway.data.ServerInfo; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.ServerUtil; -import com.gluster.storage.management.gateway.utils.SshUtil; - -/** - * Service class for functionality related to clusters - */ -@Component -public class ClusterService { - @Autowired - private PersistenceDao clusterDao; - - @Autowired - private PersistenceDao serverDao; - - @Autowired - private GlusterUtil glusterUtil; - - @Autowired - private SshUtil sshUtil; - - @Autowired - private ServerUtil serverUtil; - - private LRUCache onlineServerCache = new LRUCache(3); - - private static final Logger logger = Logger.getLogger(ClusterService.class); - - public void addOnlineServer(String clusterName, GlusterServer server) { - onlineServerCache.put(clusterName, server); - } - - public void removeOnlineServer(String clusterName) { - onlineServerCache.remove(clusterName); - } - - // uses cache - public GlusterServer getOnlineServer(String clusterName, String exceptServerName) { - GlusterServer server = onlineServerCache.get(clusterName); - if (server != null && !server.getName().equals(exceptServerName)) { - return server; - } - - return getNewOnlineServer(clusterName, exceptServerName); - } - - public GlusterServer getNewOnlineServer(String clusterName) { - return getNewOnlineServer(clusterName, ""); - } - - public GlusterServer getOnlineServer(String clusterName) { - return getOnlineServer(clusterName, ""); - } - - // Doesn't use cache - public GlusterServer getNewOnlineServer(String clusterName, String exceptServerName) { - ClusterInfo cluster = getCluster(clusterName); - if (cluster == null) { - throw new GlusterRuntimeException("Cluster [" + clusterName + "] is not found!"); - } - - for (ServerInfo serverInfo : cluster.getServers()) { - GlusterServer server = new GlusterServer(serverInfo.getName()); - try { - serverUtil.fetchServerDetails(server); // Online status come with server details - // server is online. add it to cache and return - if (server.isOnline() && !server.getName().equals(exceptServerName)) { - addOnlineServer(clusterName, server); - return server; - } - } catch (ConnectionException e) { - // server is offline. continue checking next one. - continue; - } - } - - // no online server found. - throw new GlusterRuntimeException("No online server found in cluster [" + clusterName + "]"); - } - - public List getAllClusters() { - return clusterDao.findAll(); - } - - public ClusterInfo getCluster(String clusterName) { - List clusters = clusterDao.findBy("UPPER(name) = ?1", clusterName.toUpperCase()); - if(clusters.size() == 0) { - return null; - } - - return clusters.get(0); - } - - public ClusterInfo getClusterForServer(String serverName) { - List servers = serverDao.findBy("UPPER(name) = ?1", serverName.toUpperCase()); - if(servers.size() == 0) { - return null; - } - - return servers.get(0).getCluster(); - } - - public void createCluster(String clusterName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); - - try { - clusterDao.save(cluster); - txn.commit(); - } catch (RuntimeException e) { - txn.rollback(); - logger.error("Exception while trying to save cluster [" + clusterName + "] : [" + e.getMessage() + "]", e); - throw e; - } - } - - public void registerCluster(String clusterName, String knownServer) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = new ClusterInfo(); - cluster.setName(clusterName); - - GlusterServer server = new GlusterServer(knownServer); - try { - List glusterServers = glusterUtil.getGlusterServers(server); - List servers = new ArrayList(); - 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) { - logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); - txn.rollback(); - logger.error("Error in registering cluster [" + clusterName + "] : " + e.getMessage(), e); - 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(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 { - for(ServerInfo server : cluster.getServers()) { - clusterDao.delete(server); - } - cluster.getServers().clear(); - clusterDao.update(cluster); - clusterDao.delete(cluster); - txn.commit(); - } catch (RuntimeException e) { - logger.error("Error in unregistering cluster [" + cluster.getName() + "] : " + e.getMessage(), e); - txn.rollback(); - throw e; - } - } - - public void mapServerToCluster(String clusterName, String serverName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = getCluster(clusterName); - ServerInfo server = new ServerInfo(serverName); - server.setCluster(cluster); - try { - clusterDao.save(server); - cluster.addServer(server); - clusterDao.update(cluster); - txn.commit(); - } catch (Exception e) { - txn.rollback(); - throw new GlusterRuntimeException("Couldn't create cluster-server mapping [" + clusterName + "][" - + serverName + "]! Error: " + e.getMessage(), e); - } - } - - public void unmapServerFromCluster(String clusterName, String serverName) { - EntityTransaction txn = clusterDao.startTransaction(); - ClusterInfo cluster = getCluster(clusterName); - List servers = cluster.getServers(); - for(ServerInfo server : servers) { - if(server.getName().equals(serverName)) { - servers.remove(server); - clusterDao.delete(server); - break; - } - } - try { - clusterDao.update(cluster); - txn.commit(); - } catch(Exception e) { - txn.rollback(); - throw new GlusterRuntimeException("Couldn't unmap server [" + serverName + "] from cluster [" + clusterName - + "]! Error: " + e.getMessage(), e); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java deleted file mode 100644 index d1437cec..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/services/GlusterServerService.java +++ /dev/null @@ -1,165 +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.gateway.services; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.exceptions.GlusterValidationException; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.ServerUtil; - -/** - * - */ -@Component -public class GlusterServerService { - @Autowired - protected ServerUtil serverUtil; - - @Autowired - private ClusterService clusterService; - - @Autowired - private GlusterUtil glusterUtil; - - public void fetchServerDetails(GlusterServer server) { - try { - server.setStatus(SERVER_STATUS.ONLINE); - serverUtil.fetchServerDetails(server); - } catch (ConnectionException e) { - server.setStatus(SERVER_STATUS.OFFLINE); - } - } - - public List getGlusterServers(String clusterName, boolean fetchDetails) { - List glusterServers; - GlusterServer onlineServer = clusterService.getOnlineServer(clusterName); - if (onlineServer == null) { - throw new GlusterRuntimeException("No online servers found in cluster [" + clusterName + "]"); - } - - try { - glusterServers = getGlusterServers(clusterName, onlineServer, fetchDetails); - } 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 = getGlusterServers(clusterName, onlineServer, fetchDetails); - } - return glusterServers; - } - - private List getGlusterServers(String clusterName, GlusterServer onlineServer, boolean fetchDetails) { - 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); - } - - if (fetchDetails) { - String errMsg = fetchDetailsOfServers(glusterServers, onlineServer); - if (!errMsg.isEmpty()) { - throw new GlusterRuntimeException("Couldn't fetch details for server(s): " + errMsg); - } - } - return glusterServers; - } - - private String fetchDetailsOfServers(List glusterServers, GlusterServer onlineServer) { - String errMsg = ""; - - for (GlusterServer server : glusterServers) { - try { - fetchServerDetails(server); - } catch (Exception e) { - errMsg += CoreConstants.NEWLINE + server.getName() + " : [" + e.getMessage() + "]"; - } - } - return errMsg; - } - - public GlusterServer getGlusterServer(String clusterName, String serverName, Boolean fetchDetails) { - if (clusterName == null || clusterName.isEmpty()) { - throw new GlusterValidationException("Cluster name must not be empty!"); - } - - if (serverName == null || serverName.isEmpty()) { - throw new GlusterValidationException("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 + "]"); - } - - return getGlusterServer(clusterName, serverName, onlineServer, fetchDetails); - } - - private GlusterServer getGlusterServer(String clusterName, String serverName, GlusterServer onlineServer, - Boolean fetchDetails) { - 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 (fetchDetails && server.isOnline()) { - fetchServerDetails(server); - } - return server; - } - - public boolean isValidServer(String clusterName, String serverName) { - try { - GlusterServer server = getGlusterServer(clusterName, serverName, false); - return server != null; - } catch(Exception e) { - return false; - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java deleted file mode 100644 index 6d525785..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitServerTask.java +++ /dev/null @@ -1,162 +0,0 @@ -/** - * GlusterServerInitializer.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.gateway.tasks; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import javax.servlet.ServletContext; - -import org.apache.derby.tools.ij; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.RowCallbackHandler; -import org.springframework.jdbc.core.support.JdbcDaoSupport; -import org.springframework.security.authentication.encoding.PasswordEncoder; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.data.PersistenceDao; - -/** - * Initializes the Gluster Management Server. - */ -public class InitServerTask extends JdbcDaoSupport { - @Autowired - private PasswordEncoder passwordEncoder; - - @Autowired - private String appVersion; - - @Autowired - private PersistenceDao clusterDao; - - @Autowired - ServletContext servletContext; - - private static final String SCRIPT_DIR = "data/scripts/"; - - public void securePasswords() { - getJdbcTemplate().query("select username, password from users", new RowCallbackHandler() { - @Override - public void processRow(ResultSet rs) throws SQLException { - String username = rs.getString(1); - String password = rs.getString(2); - String encodedPassword = passwordEncoder.encodePassword(password, null); - getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword, username); - logger.debug("Updating password for username: " + username); - } - }); - } - - private void executeScript(File script) { - ByteArrayOutputStream sqlOut = new ByteArrayOutputStream(); - int numOfExceptions; - try { - numOfExceptions = ij.runScript(getJdbcTemplate().getDataSource().getConnection(), new FileInputStream( - script), CoreConstants.ENCODING_UTF8, sqlOut, CoreConstants.ENCODING_UTF8); - String output = sqlOut.toString(); - sqlOut.close(); - logger.debug("Data script [" + script.getName() + "] returned with exit status [" + numOfExceptions - + "] and output [" + output + "]"); - if (numOfExceptions != 0) { - throw new GlusterRuntimeException("Server data initialization script [ " + script.getName() - + "] failed with [" + numOfExceptions + "] exceptions! [" + output + "]"); - } - } catch (Exception ex) { - throw new GlusterRuntimeException("Server data initialization script [" + script.getName() + "] failed!", - ex); - } - } - - private void initDatabase() { - logger.info("Initializing server data..."); - executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + appVersion)); - - securePasswords(); // encrypt the passwords - } - - private File getDirFromRelativePath(String relativePath) { - String scriptDirPath = servletContext.getRealPath(relativePath); - File scriptDir = new File(scriptDirPath); - return scriptDir; - } - - private void executeScriptsFrom(File scriptDir) { - if (!scriptDir.exists()) { - throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] doesn't exist!"); - } - - List scripts = Arrays.asList(scriptDir.listFiles()); - if(scripts.size() == 0) { - throw new GlusterRuntimeException("Script directory [" + scriptDir.getAbsolutePath() + "] is empty!"); - } - - Collections.sort(scripts); - for (File script : scripts) { - executeScript(script); - } - } - - /** - * Initializes the server database, if running for the first time. - */ - public synchronized void initServer() { - try { - String dbVersion = getDBVersion(); - if (!appVersion.equals(dbVersion)) { - logger.info("App version [" + appVersion + "] differs from data version [" + dbVersion - + "]. Trying to upgrade data..."); - upgradeData(dbVersion, appVersion); - } - } catch (Exception ex) { - logger.info("No cluster created yet. DB version query failed with error [" + ex.getMessage() + "]", ex); - // Database not created yet. Create it! - initDatabase(); - } - - // For development time debugging. To be removed later. - List clusters = clusterDao.findAll(); - logger.info(clusters.size()); - - if (clusters.size() > 0) { - for (ClusterInfo cluster : clusters) { - logger.info("Cluster: [" + cluster.getId() + "][" + cluster.getName() + "]"); - } - } else { - - } - } - - private void upgradeData(String fromVersion, String toVersion) { - executeScriptsFrom(getDirFromRelativePath(SCRIPT_DIR + fromVersion + "-" + toVersion)); - } - - private String getDBVersion() { - return (String) clusterDao.getSingleResultFromSQL("select version from version"); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java deleted file mode 100644 index e7da1de6..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/InitializeDiskTask.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * InitializeDiskTask.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.gateway.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.constants.GlusterConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.ServerUtil; -import com.gluster.storage.management.gateway.utils.SshUtil; -import com.sun.jersey.core.util.Base64; - -public class InitializeDiskTask extends Task { - - private static final String INITIALIZE_DISK_SCRIPT = "format_device.py"; - - private String serverName; - private String diskName; - private String fsType; - private ServerUtil serverUtil; - private GlusterUtil glusterUtil; - - public InitializeDiskTask(ClusterService clusterService, String clusterName, String serverName, String diskName, String fsType) { - super(clusterService, clusterName, TASK_TYPE.DISK_FORMAT, diskName, "Initialize disk " + serverName + ":" - + diskName, false, false, false); - - setServerName(serverName); - setDiskName(diskName); - setFsType(fsType); - taskInfo.setName(getId()); - init(); - } - - public InitializeDiskTask(ClusterService clusterService, String clusterName, TaskInfo info) { - super(clusterService, clusterName, info); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - glusterUtil = ctx.getBean(GlusterUtil.class); - serverUtil = ctx.getBean(ServerUtil.class); - } - - @Override - public String getId() { - return new String( - Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + serverName + ":" + diskName)); - } - - @Override - public void resume() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void stop() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void pause() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Stop/Pause/Resume is not supported in Disk Initialization"))); - } - - @Override - public void commit() { - // TODO Auto-generated method stub - } - - @Override - public TASK_TYPE getType() { - return TASK_TYPE.DISK_FORMAT; - } - - - @Override - public void start() { - try { - startInitializeDisk(serverName); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - } - } - - private void startInitializeDisk(String serverName) { - String fsTypeCommand = (getFsType().equals(GlusterConstants.FSTYPE_DEFAULT)) ? "" : " -t " + getFsType(); - - String output = (String) serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_SCRIPT - + fsTypeCommand + " " + getDiskName(), String.class); - TaskStatus taskStatus = new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output)); - taskStatus.setPercentageSupported((getFsType().equals(GlusterConstants.FSTYPE_XFS)) ? false : true); - getTaskInfo().setStatus(taskStatus); - } - - @Override - public TaskStatus checkStatus() { - - try { - return glusterUtil.getInitializingDeviceStatus(serverName, getDiskName()); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - return new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage())); - } - } - - public void setDiskName(String diskName) { - this.diskName = diskName; - } - - public String getDiskName() { - return diskName; - } - - public void setServerName(String serverName) { - this.serverName = serverName; - } - - public String getServerName() { - return serverName; - } - - public void setFsType(String fsType) { - this.fsType = fsType; - } - - public String getFsType() { - return fsType; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java deleted file mode 100644 index 694067aa..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/MigrateBrickTask.java +++ /dev/null @@ -1,227 +0,0 @@ -/** - * MigrateDiskTask.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.gateway.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.sun.jersey.core.util.Base64; - -public class MigrateBrickTask extends Task { - - private String fromBrick; - private String toBrick; - private Boolean autoCommit; - private GlusterUtil glusterUtil; - - public String getFromBrick() { - return fromBrick; - } - - public void setFromBrick(String fromBrick) { - this.fromBrick = fromBrick; - } - - public String getToBrick() { - return toBrick; - } - - public void setToBrick(String toBrick) { - this.toBrick = toBrick; - } - - public Boolean getAutoCommit() { - return autoCommit; - } - - public void setAutoCommit(Boolean autoCommit) { - this.autoCommit = autoCommit; - } - - public MigrateBrickTask(ClusterService clusterService, String clusterName, String volumeName, String fromBrick, - String toBrick) { - super(clusterService, clusterName, TASK_TYPE.BRICK_MIGRATE, volumeName, "Brick Migration on volume [" - + volumeName + "] from [" + fromBrick + "] to [" + toBrick + "]", true, true, true); - setFromBrick(fromBrick); - setToBrick(toBrick); - taskInfo.setName(getId()); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - glusterUtil = ctx.getBean(GlusterUtil.class); - } - - @Override - public String getId() { - return new String(Base64.encode(clusterName + "-" + taskInfo.getType() + "-" + taskInfo.getReference() + "-" + fromBrick + "-" - + toBrick)); - } - - @Override - public void start() { - try { - startMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone Offline. try with a new one. - startMigration(getNewOnlineServer().getName()); - } - } - - private void startMigration(String onlineServerName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServerName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "start"); - if (processResult.getOutput().trim().matches(".*started successfully$")) { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, processResult.getOutput().trim()))); - return; - } - } - - @Override - public void pause() { - try { - pauseMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - pauseMigration(getNewOnlineServer().getName()); - } - } - - private void pauseMigration(String onlineServer) { - ProcessResult processResult = glusterUtil.executeBrickMigration(onlineServer, taskInfo.getReference(), - getFromBrick(), getToBrick(), "pause"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.getOutput().trim().matches(".*paused successfully$")) { - taskStatus.setCode(Status.STATUS_CODE_PAUSE); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - return; - } - } - - @Override - public void resume() { - start(); - } - - @Override - public void commit() { - try { - commitMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - commitMigration(getNewOnlineServer().getName()); - } - } - - private void commitMigration(String serverName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "commit"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches(".*commit successful$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - } - } - } - - @Override - public void stop() { - try { - stopMigration(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - stopMigration(getNewOnlineServer().getName()); - } - } - - private void stopMigration(String serverName) { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, taskInfo.getReference(), getFromBrick(), - getToBrick(), "abort"); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.getOutput().trim().matches(".*aborted successfully$")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - getTaskInfo().setStatus(taskStatus); - } - } - - @Override - public TaskStatus checkStatus() { - try { - return checkMigrationStatus(getOnlineServer().getName()); - } catch (ConnectionException e) { - // online server might have gone offline. try with a new one. - return checkMigrationStatus(getNewOnlineServer().getName()); - } - } - - private TaskStatus checkMigrationStatus(String serverName) { - if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_PAUSE) { - return getTaskInfo().getStatus(); - } - // For committed task, status command (CLI) is invalid, just return current status - if (getTaskInfo().getStatus().getCode() == Status.STATUS_CODE_SUCCESS) { - return getTaskInfo().getStatus(); - } - - - TaskStatus taskStatus = new TaskStatus(); - try { - ProcessResult processResult = glusterUtil.executeBrickMigration(serverName, getTaskInfo().getReference(), - getFromBrick(), getToBrick(), "status"); - if (processResult.getOutput().trim().matches("^Number of files migrated.*Migration complete$") - || processResult.getOutput().trim().matches("^Number of files migrated = 0 .*Current file=")) { - // Note: Workaround - if no file in the volume brick to migrate, Gluster CLI is not giving proper - // (complete) status - taskStatus.setCode(Status.STATUS_CODE_COMMIT_PENDING); - if (autoCommit) { - commitMigration(serverName); - return getTaskInfo().getStatus(); // return the committed status - } else { - taskStatus.setMessage(processResult.getOutput().trim() - .replaceAll("Migration complete", "Commit pending")); - } - } else if (processResult.getOutput().trim().matches("^Number of files migrated.*Current file=.*")) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - taskStatus.setMessage(processResult.getOutput()); - } catch (Exception e) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - taskStatus.setMessage(e.getMessage()); - } - taskInfo.setStatus(taskStatus); // Update the task status - return taskStatus; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java deleted file mode 100644 index c53f0252..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/RebalanceVolumeTask.java +++ /dev/null @@ -1,129 +0,0 @@ -/** - * RebalanceVolumeTask.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.gateway.tasks; - -import org.springframework.context.ApplicationContext; -import org.springframework.web.context.ContextLoader; - -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.utils.GlusterUtil; -import com.gluster.storage.management.gateway.utils.ServerUtil; -import com.gluster.storage.management.gateway.utils.SshUtil; -import com.sun.jersey.core.util.Base64; - -public class RebalanceVolumeTask extends Task { - - private String layout; - private String serverName; - private ServerUtil serverUtil; - private GlusterUtil glusterUtil; - - public RebalanceVolumeTask(ClusterService clusterService, String clusterName, String volumeName, String layout) { - super(clusterService, clusterName, TASK_TYPE.VOLUME_REBALANCE, volumeName, "Volume " + volumeName - + " Rebalance", false, true, false); - setLayout(layout); - taskInfo.setName(getId()); - init(); - } - - private void init() { - ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); - serverUtil = ctx.getBean(ServerUtil.class); - glusterUtil = ctx.getBean(GlusterUtil.class); - } - - @Override - public String getId() { - return new String(Base64.encode(getClusterName() + "-" + taskInfo.getType() + "-" + taskInfo.getReference())); - } - - @Override - public void start() { - try { - serverName = getOnlineServer().getName(); - startRebalance(serverName); - } catch(ConnectionException e) { - // online server might have gone offline. try with a new one - serverName = getNewOnlineServer().getName(); - startRebalance(serverName); - } - } - - private void startRebalance(String serverName) { - String command = "gluster volume rebalance " + getTaskInfo().getReference() + " " + getLayout() + " start"; - String output = (String)serverUtil.executeOnServer(true, serverName, command, String.class); - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_RUNNING, output))); - } - - @Override - public void resume() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Pause/Resume is not supported in Volume Rebalance"))); - } - - @Override - public void stop() { - try { - glusterUtil.stopRebalance(serverName, getTaskInfo().getReference()); - } catch (ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - } - } - - @Override - public void pause() { - getTaskInfo().setStatus( - new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, - "Pause/Resume is not supported in Volume Rebalance"))); - } - - @Override - public TaskStatus checkStatus() { - try { - return glusterUtil.checkRebalanceStatus(serverName, getTaskInfo().getReference()); - } catch(ConnectionException e) { - // online server might have gone offline. update the failure status - getTaskInfo().setStatus(new TaskStatus(new Status(Status.STATUS_CODE_FAILURE, e.getMessage()))); - return getTaskInfo().getStatus(); - } - } - - public void setLayout(String layout) { - this.layout = layout; - } - - public String getLayout() { - return layout; - } - - @Override - public void commit() { - // TODO Auto-generated method stub - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java deleted file mode 100644 index 94c743aa..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/ServerSyncTask.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * ServerDiscoveryTask.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.gateway.tasks; - -import java.util.ArrayList; -import java.util.List; - -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.GlusterConstants; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.utils.GlusterCoreUtil; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.gateway.data.ClusterInfo; -import com.gluster.storage.management.gateway.data.PersistenceDao; -import com.gluster.storage.management.gateway.data.ServerInfo; -import com.gluster.storage.management.gateway.resources.v1_0.DiscoveredServersResource; -import com.gluster.storage.management.gateway.services.ClusterService; -import com.gluster.storage.management.gateway.services.GlusterServerService; -import com.gluster.storage.management.gateway.utils.ServerUtil; - -/** - * Task for syncing server details. This performs two things:
- * 1. Auto-discovery of servers eligible to be added to the Gluster cluster.
- * 2. Syncing of cluster-server mapping with actual servers of the cluster. This mapping can go out of sync if user - * adds/removes servers manually using the CLI. - */ -@Component -public class ServerSyncTask { - private static final String SCRIPT_NAME_SFX = "-discover-servers.py"; - - @Autowired - private ServerUtil serverUtil; - - @Autowired - private DiscoveredServersResource discoveredServersResource; - - @Autowired - private GlusterServerService glusterServerService; - - @Autowired - private String discoveryMechanism; - - @Autowired - private ClusterService clusterService; - - @Autowired - private PersistenceDao clusterDao; - - public void perform() { - discoverServers(); - syncClusterServerMapping(); - } - - private void syncClusterServerMapping() { - List clusters = clusterService.getAllClusters(); - for(ClusterInfo cluster : clusters) { - List servers = cluster.getServers(); - List actualServers = glusterServerService.getGlusterServers(cluster.getName(), false); - updateRemovedServers(cluster, servers, actualServers); - updateAddedServers(cluster, servers, actualServers); - } - } - - private void updateAddedServers(ClusterInfo cluster, List servers, List actualServers) { - List addedServers = findAddedServers(cluster.getName(), servers, actualServers); - for(String addedServer : addedServers) { - clusterService.mapServerToCluster(cluster.getName(), addedServer); - } - } - - private void updateRemovedServers(ClusterInfo cluster, List servers, List actualServers) { - List removedServers = findRemovedServers(servers, actualServers); - for(String removedServer : removedServers) { - clusterService.unmapServerFromCluster(cluster.getName(), removedServer); - } - } - - private List findRemovedServers(List servers, List actualServers) { - List removedServers = new ArrayList(); - - for(ServerInfo server : servers) { - if (!GlusterCoreUtil.containsEntityWithName(actualServers, server.getName(), true)) { - removedServers.add(server.getName()); - } - } - return removedServers; - } - - private List findAddedServers(String clusterName, List servers, List actualServers) { - List addedServers = new ArrayList(); - for(GlusterServer actualServer : actualServers) { - if(!serverExists(servers, actualServer.getName())) { - addedServers.add(actualServer.getName()); - } - } - return addedServers; - } - - private boolean serverExists(List servers, String name) { - for(ServerInfo server : servers) { - if(server.getName().equalsIgnoreCase(name)) { - return true; - } - } - return false; - } - - @SuppressWarnings("unchecked") - private void discoverServers() { - if(discoveryMechanism.equals(GlusterConstants.NONE)) { - return; - } - - List serverNameList = new ArrayList(); - - ProcessResult result = serverUtil.executeGlusterScript(true, discoveryMechanism + SCRIPT_NAME_SFX, new ArrayList()); - if(result.isSuccess()) { - List existingServers = clusterDao.findBySQL("select name from server_info"); - String serverNames = result.getOutput(); - String[] parts = serverNames.split(CoreConstants.NEWLINE); - for(String serverName : parts) { - // The server discovery mechanism will return every server that has not been "peer probed". However we - // need to filter out those servers that are the "first" server of a new cluster, and hence are still - // not peer probed. - if(!existingServers.contains(serverName)) { - serverNameList.add(serverName); - } - } - } - - discoveredServersResource.setDiscoveredServerNames(serverNameList); - } -} \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java deleted file mode 100644 index 1ba360bc..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/tasks/Task.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Task.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.gateway.tasks; - -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.TaskInfo; -import com.gluster.storage.management.core.model.TaskInfo.TASK_TYPE; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.gateway.services.ClusterService; - -public abstract class Task { - public String[] TASK_TYPE_STR = { "Format Disk", "Migrate Brick", "Volume Rebalance" }; - - protected TaskInfo taskInfo; - protected String clusterName; - private ClusterService clusterService; - - public Task(ClusterService clusterService, String clusterName, TASK_TYPE type, String reference, String desc, - boolean canPause, boolean canStop, boolean canCommit) { - TaskInfo taskInfo = new TaskInfo(); - taskInfo.setType(type); - taskInfo.setReference(reference); - taskInfo.setDescription(desc); - taskInfo.setPauseSupported(canPause); - taskInfo.setStopSupported(canStop); - taskInfo.setCommitSupported(canCommit); - - init(clusterService, clusterName, taskInfo); - - } - - public Task(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { - init(clusterService, clusterName, taskInfo); - } - - private void init(ClusterService clusterService, String clusterName, TaskInfo taskInfo) { - this.clusterService = clusterService; - setClusterName(clusterName); - setTaskInfo(taskInfo); - } - - protected GlusterServer getOnlineServer() { - return clusterService.getOnlineServer(clusterName); - } - - protected GlusterServer getNewOnlineServer() { - return clusterService.getNewOnlineServer(clusterName); - } - - protected GlusterServer getNewOnlineServer(String exceptServerName) { - return clusterService.getNewOnlineServer(clusterName, exceptServerName); - } - - public String getTypeStr() { - return TASK_TYPE_STR[taskInfo.getType().ordinal()]; - } - - public TASK_TYPE getType() { - return getTaskInfo().getType(); - } - - public String getClusterName() { - return clusterName; - } - - public void setClusterName(String clusterName) { - this.clusterName = clusterName; - } - - public TaskInfo getTaskInfo() { - return taskInfo; - } - - public void setTaskInfo(TaskInfo info) { - this.taskInfo = info; - } - - public abstract String getId(); - - public abstract void start(); - - public abstract void resume(); - - public abstract void stop(); - - public abstract void pause(); - - public abstract void commit(); - - /** - * This method should check current status of the task and update it's taskInfo accordingly - */ - public abstract TaskStatus checkStatus(); -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java deleted file mode 100644 index 13a58729..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/AbstractStatsFactory.java +++ /dev/null @@ -1,169 +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.gateway.utils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; -import com.gluster.storage.management.core.model.Status; - -/** - * - */ -@Component -public abstract class AbstractStatsFactory implements StatsFactory { - @Autowired - protected ServerUtil serverUtil; - - private Logger logger = Logger.getLogger(AbstractStatsFactory.class); - - protected ServerStats getFirstOnlineServerStats(List serverNames, String period, - boolean removeServerOnError, boolean removeOnlineServer) { - for(int i = serverNames.size() - 1; i >= 0; i--) { - String serverName = serverNames.get(i); - try { - ServerStats stats = fetchStats(serverName, period); - if(removeOnlineServer) { - serverNames.remove(serverName); - } - return stats; - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); - if(removeServerOnError) { - serverNames.remove(serverName); - } - continue; - } - } - throw new GlusterRuntimeException("All servers offline!"); - } - - protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { - if(serverNames.isEmpty()) { - return; - } - - int rowCount = aggregatedStats.getMetadata().getRowCount(); - int columnCount = aggregatedStats.getMetadata().getLegend().size(); - int[][] dataCount = initDataCountArray(rowCount, columnCount); - - for (String serverName : serverNames) { - try { - // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period), aggregatedStats, dataCount); - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch performance stats from server [" + serverName + "]!", e); - continue; - } - } - - averageAggregatedStats(aggregatedStats, dataCount); - } - - /** - * - * @param statsToBeAdded - * @param targetStats - * @param dataCount Each element of this matrix will be incremented for every valid element added - * @return - */ - protected List addServerStats(ServerStats statsToBeAdded, ServerStats targetStats, int[][] dataCount) { - List serverStatsRows = statsToBeAdded.getRows(); - for (int rowNum = 0; rowNum < serverStatsRows.size() - && rowNum < targetStats.getMetadata().getRowCount(); rowNum++) { - ServerStatsRow row = serverStatsRows.get(rowNum); - List rowData = row.getUsageData(); - - List aggregatedStatsRowData = targetStats.getRows().get(rowNum).getUsageData(); - for(int i = 1; i < targetStats.getMetadata().getLegend().size(); i++) { - // Add the data - Double data = rowData.get(i); - if(!data.isNaN()) { - // data is available. add it. - aggregatedStatsRowData.set(i, aggregatedStatsRowData.get(i) + data); - // increment record count. this will be used for calculating average of aggregated data. - dataCount[rowNum][i]++; - } - } - } - return serverStatsRows; - } - - protected void averageAggregatedStats(ServerStats aggregatedStats, int[][] dataCount) { - List rows = aggregatedStats.getRows(); - for(int rowNum = 0; rowNum < rows.size(); rowNum++) { - List data = rows.get(rowNum).getUsageData(); - for(int columnNum = 0; columnNum < data.size(); columnNum++) { - data.set(columnNum, data.get(columnNum) / dataCount[rowNum][columnNum]); - } - } - } - - protected int[][] initDataCountArray(int rowCount, int columnCount) { - int[][] dataCount = new int[rowCount][columnCount]; - // initialize all data counts to 1 - for(int rowNum = 0; rowNum < rowCount; rowNum++) { - for(int columnNum = 0; columnNum < columnCount; columnNum++) { - dataCount[rowNum][columnNum] = 1; - } - } - return dataCount; - } - - @Override - public ServerStats fetchAggregatedStats(List serverNames, String period) { - if(serverNames == null || serverNames.size() == 0) { - throw new GlusterRuntimeException("No server names passed to fetchAggregaredStats!"); - } - - ServerStats firstServerStats = getFirstOnlineServerStats(serverNames, period, true, true); - - ServerStats aggregatedStats = new ServerStats(firstServerStats); - aggregateStats(serverNames, aggregatedStats, period); - return aggregatedStats; - } - - @Override - public ServerStats fetchStats(String serverName, String period, String...args) { - String argsStr = ""; - for (String arg : args) { - if(arg != null) { - argsStr += " " + arg; - } - } - Object output = serverUtil.executeScriptOnServer(true, serverName, getStatsScriptName() + argsStr + " " - + period, ServerStats.class); - //String cpuUsageData = " 1310468100 300 1310471700 13 3 user system total 13104681002.23802952e-14.3747778209e-016.6128073384e-01 13104684002.3387347338e-014.4642717442e-016.8030064780e-01 13104687005.5043873220e+006.2462376636e+001.1750624986e+01 13104690002.4350593653e+012.6214585217e+015.0565178869e+01 13104693004.0786489953e+014.6784713828e+018.7571203781e+01 13104696004.1459955508e+015.2546309044e+019.4006264551e+01 13104699004.2312286165e+015.2390588332e+019.4702874497e+01 13104702004.2603794982e+015.1598861493e+019.4202656475e+01 13104705003.8238751290e+014.5312089966e+018.3550841256e+01 13104708001.7949961224e+012.1282058418e+013.9232019642e+01 13104711001.2330371421e-014.6347832868e-015.8678204289e-01 13104714001.6313260492e-015.4088119561e-017.0401380052e-01 1310471700NaNNaNNaN "; - //Object output = unmarshal(ServerStats.class, cpuUsageData, false); - if(output instanceof Status) { - throw new GlusterRuntimeException(((Status)output).toString()); - } - return (ServerStats) output; - } - - public abstract String getStatsScriptName(); -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java deleted file mode 100644 index b6ef9ef2..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/CpuStatsFactory.java +++ /dev/null @@ -1,36 +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.gateway.utils; - -import org.springframework.stereotype.Component; - -/** - * - */ -@Component -public class CpuStatsFactory extends AbstractStatsFactory { - - private static final String CPU_STATS_SCRIPT = "get_rrd_cpu_details.py"; - - @Override - public String getStatsScriptName() { - return CPU_STATS_SCRIPT; - } - -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java deleted file mode 100644 index 55909d54..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/GlusterUtil.java +++ /dev/null @@ -1,662 +0,0 @@ -/** - * GlusterUtil.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.gateway.utils; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.regex.Pattern; - -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.GlusterConstants; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Brick; -import com.gluster.storage.management.core.model.Brick.BRICK_STATUS; -import com.gluster.storage.management.core.model.GlusterServer; -import com.gluster.storage.management.core.model.InitDiskStatusResponse; -import com.gluster.storage.management.core.model.InitDiskStatusResponse.FORMAT_STATUS; -import com.gluster.storage.management.core.model.Server.SERVER_STATUS; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.model.TaskStatus; -import com.gluster.storage.management.core.model.Volume; -import com.gluster.storage.management.core.model.Volume.TRANSPORT_TYPE; -import com.gluster.storage.management.core.model.Volume.VOLUME_STATUS; -import com.gluster.storage.management.core.model.Volume.VOLUME_TYPE; -import com.gluster.storage.management.core.utils.GlusterCoreUtil; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.core.utils.StringUtil; -import com.gluster.storage.management.gateway.resources.v1_0.TasksResource; - -@Component -public class GlusterUtil { - private static final String glusterFSminVersion = "3.1"; - - private static final String HOSTNAME_PFX = "Hostname:"; - private static final String UUID_PFX = "Uuid:"; - private static final String STATE_PFX = "State:"; - private static final String GLUSTER_SERVER_STATUS_ONLINE = "Connected"; - - private static final String VOLUME_NAME_PFX = "Volume Name:"; - private static final String VOLUME_TYPE_PFX = "Type:"; - private static final String VOLUME_STATUS_PFX = "Status:"; - private static final String VOLUME_NUMBER_OF_BRICKS = "Number of Bricks:"; - private static final String VOLUME_TRANSPORT_TYPE_PFX = "Transport-type:"; - private static final String VOLUME_BRICKS_GROUP_PFX = "Bricks"; - private static final String VOLUME_OPTIONS_RECONFIG_PFX = "Options Reconfigured"; - private static final String VOLUME_OPTION_AUTH_ALLOW_PFX = "auth.allow:"; - private static final String VOLUME_LOG_LOCATION_PFX = "log file location:"; - private static final String VOLUME_TYPE_DISTRIBUTE = "Distribute"; - private static final String VOLUME_TYPE_REPLICATE = "Replicate"; - private static final String GLUSTERD_INFO_FILE = "/etc/glusterd/glusterd.info"; - - private static final GlusterCoreUtil glusterCoreUtil = new GlusterCoreUtil(); - - private static final String INITIALIZE_DISK_STATUS_SCRIPT = "get_format_device_status.py"; - - @Autowired - private SshUtil sshUtil; - - @Autowired - private ServerUtil serverUtil; - - @Autowired - private TasksResource taskResource; - - public void setSshUtil(SshUtil sshUtil) { - this.sshUtil = sshUtil; - } - - public SshUtil getSshUtil() { - return sshUtil; - } - - /** - * Extract value of given token from given line. It is assumed that the token, if present, will be of the following - * form: token: value - * - * @param line - * Line to be analyzed - * @param token - * Token whose value is to be extracted - * @return Value of the token, if present in the line - */ - private final String extractToken(String line, String token) { - if (line.contains(token)) { - return line.split(token)[1].trim(); - } - return null; - } - - public GlusterServer getGlusterServer(GlusterServer onlineServer, String serverName) { - List servers = getGlusterServers(onlineServer); - for (GlusterServer server : servers) { - if (server.getName().equals(serverName)) { - return server; - } - } - return null; - } - - private String getUuid(String serverName) { - ProcessResult result = getSshUtil().executeRemote(serverName, "cat " + GLUSTERD_INFO_FILE); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't read file [" + GLUSTERD_INFO_FILE + "]. Error: " - + result.toString()); - } - return result.getOutput().split("=")[1]; - } - - public List getGlusterServers(GlusterServer knownServer) { - String output = getPeerStatus(knownServer.getName()); - if (output == null) { - return null; - } - - knownServer.setUuid(getUuid(knownServer.getName())); - - List glusterServers = new ArrayList(); - glusterServers.add(knownServer); - - GlusterServer server = null; - boolean foundHost = false; - boolean foundUuid = false; - for (String line : output.split(CoreConstants.NEWLINE)) { - if (foundHost && foundUuid) { - // Host and UUID is found, we should look for state - String state = extractToken(line, STATE_PFX); - if (state != null) { - server.setStatus(state.contains(GLUSTER_SERVER_STATUS_ONLINE) ? SERVER_STATUS.ONLINE - : SERVER_STATUS.OFFLINE); - // Completed populating current server. Add it to the list - // and reset all related variables. - glusterServers.add(server); - - foundHost = false; - foundUuid = false; - server = null; - } - } else if (foundHost) { - // Host is found, look for UUID - String uuid = extractToken(line, UUID_PFX); - if (uuid != null) { - server.setUuid(uuid); - foundUuid = true; - } - } else { - // Look for the next host - if (server == null) { - server = new GlusterServer(); - } - String hostName = extractToken(line, HOSTNAME_PFX); - if (hostName != null) { - server.setName(hostName); - foundHost = true; - } - } - - } - return glusterServers; - } - - public List getGlusterServerNames(String knownServer) { - String output = getPeerStatus(knownServer); - if (output == null) { - return null; - } - - List glusterServerNames = new ArrayList(); - for (String line : output.split(CoreConstants.NEWLINE)) { - String hostName = extractToken(line, HOSTNAME_PFX); - if (hostName != null) { - glusterServerNames.add(hostName); - } - } - return glusterServerNames; - } - - /** - * @param knownServer - * A known server on which the gluster command will be executed to fetch peer status - * @return Outout of the "gluster peer status" command - */ - private String getPeerStatus(String knownServer) { - String output; - ProcessResult result = getSshUtil().executeRemote(knownServer, "gluster peer status"); - if (!result.isSuccess()) { - output = null; - } - output = result.getOutput(); - return output; - } - - public void addServer(String existingServer, String newServer) { - ProcessResult result = sshUtil.executeRemote(existingServer, "gluster peer probe " + newServer); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't probe server [" + newServer + "] from [" + existingServer - + "]. Error: " + result); - } - - // reverse peer probe to ensure that host names appear in peer status on both sides - result = sshUtil.executeRemote(newServer, "gluster peer probe " + existingServer); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't _reverse_ probe server [" + existingServer + "] from [" - + newServer + "]. Error: " + result); - } - } - - public Status startVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster volume start " + volumeName)); - } - - public Status stopVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume stop " + volumeName)); - } - - public void resetOptions(String volumeName, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume reset " + volumeName); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't reset options for volume [" + volumeName + "]! Error: " - + result); - } - } - - public void createVolume(String knownServer, String volumeName, String volumeTypeStr, String transportTypeStr, - Integer replicaCount, Integer stripeCount, String bricks, String accessProtocols, String options) { - - int count = 1; // replica or stripe count - - VOLUME_TYPE volType = Volume.getVolumeTypeByStr(volumeTypeStr); - String volTypeArg = null; - if (volType == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - volTypeArg = "replica"; - count = replicaCount; - } else if (volType == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - volTypeArg = "stripe"; - count = stripeCount; - } - - String transportTypeArg = null; - TRANSPORT_TYPE transportType = Volume.getTransportTypeByStr(transportTypeStr); - transportTypeArg = (transportType == TRANSPORT_TYPE.ETHERNET) ? "tcp" : "rdma"; - - String command = prepareVolumeCreateCommand(volumeName, StringUtil.extractList(bricks, ","), count, - volTypeArg, transportTypeArg); - ProcessResult result = sshUtil.executeRemote(knownServer, command); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Error in creating volume [" + volumeName + "]: " + result); - } - - try { - createOptions(volumeName, StringUtil.extractMap(options, ",", "="), knownServer); - } catch(Exception e) { - throw new GlusterRuntimeException( - "Volume created successfully, however following errors occurred while setting options: " - + CoreConstants.NEWLINE + e.getMessage()); - } - } - - private String prepareVolumeCreateCommand(String volumeName, List brickDirectories, int count, - String volumeType, String transportTypeStr) { - StringBuilder command = new StringBuilder("gluster volume create " + volumeName + " "); - if (volumeType != null) { - command.append(volumeType + " " + count + " "); - } - command.append("transport " + transportTypeStr); - for (String brickDir : brickDirectories) { - command.append(" " + brickDir); - } - return command.toString(); - } - - public void createOptions(String volumeName, Map options, String knownServer) { - String errors = ""; - if (options != null) { - for (Entry option : options.entrySet()) { - String key = option.getKey(); - String value = option.getValue(); - - try { - setOption(volumeName, key, value, knownServer); - } catch(Exception e) { - // append error - errors += e.getMessage() + CoreConstants.NEWLINE; - } - } - } - if (!errors.trim().isEmpty()) { - throw new GlusterRuntimeException("Errors while setting option(s) on volume [" + volumeName + "] : " - + errors.trim()); - } - } - - public void setOption(String volumeName, String key, String value, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume set " + volumeName + " " + key + " " - + "\"" + value + "\""); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Volume [" + volumeName + "] set [" + key + "=" + value + "] => " - + result); - } - } - - public Status deleteVolume(String volumeName, String knownServer) { - return new Status(sshUtil.executeRemote(knownServer, "gluster --mode=script volume delete " + volumeName)); - } - - private String getVolumeInfo(String volumeName, String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info " + volumeName); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [gluster volume info " + volumeName + "] failed on [" - + knownServer + "] with error: " + result); - } - return result.getOutput(); - } - - private String getVolumeInfo(String knownServer) { - ProcessResult result = sshUtil.executeRemote(knownServer, "gluster volume info "); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [gluster volume info] failed on [" + knownServer - + "] with error: " + result); - } - return result.getOutput(); - } - - private boolean readVolumeType(Volume volume, String line) { - String volumeType = extractToken(line, VOLUME_TYPE_PFX); - if (volumeType != null) { - if (volumeType.equals(VOLUME_TYPE_DISTRIBUTE)) { - volume.setVolumeType(VOLUME_TYPE.PLAIN_DISTRIBUTE); - } else if (volumeType.equals(VOLUME_TYPE_REPLICATE)) { - volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_MIRROR); - volume.setReplicaCount(Volume.DEFAULT_REPLICA_COUNT); - } else { - volume.setVolumeType(VOLUME_TYPE.DISTRIBUTED_STRIPE); - volume.setStripeCount(Volume.DEFAULT_STRIPE_COUNT); - } - return true; - } - return false; - } - - private void readReplicaOrStripeCount(Volume volume, String line) { - if (extractToken(line, "x") != null) { - // expected formated of line is "Number of Bricks: 3 x 2 = 6" - int count = Integer.parseInt(line.split("x")[1].split("=")[0].trim()); - if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_STRIPE) { - volume.setStripeCount(count); - } else if (volume.getVolumeType() == VOLUME_TYPE.DISTRIBUTED_MIRROR) { - volume.setReplicaCount(count); - volume.setStripeCount(0); - } - - } - return; - } - - private boolean readVolumeStatus(Volume volume, String line) { - String volumeStatus = extractToken(line, VOLUME_STATUS_PFX); - if (volumeStatus != null) { - volume.setStatus(volumeStatus.equals("Started") ? VOLUME_STATUS.ONLINE : VOLUME_STATUS.OFFLINE); - return true; - } - return false; - } - - private boolean readTransportType(Volume volume, String line) { - String transportType = extractToken(line, VOLUME_TRANSPORT_TYPE_PFX); - if (transportType != null) { - volume.setTransportType(transportType.equals("tcp") ? TRANSPORT_TYPE.ETHERNET : TRANSPORT_TYPE.INFINIBAND); - return true; - } - return false; - } - - private boolean readBrick(Volume volume, String brickLine) { - BRICK_STATUS brickStatus; - if (brickLine.matches("Brick[0-9]+:.*")) { - // line: "Brick1: server1:/export/md0/volume-name" - String brickName = brickLine.split(": ")[1]; - String[] brickParts = brickLine.split(":"); - String serverName = brickParts[1].trim(); - String brickDir = brickParts[2].trim(); - //To get the brick status - brickStatus = getBrickStatus(serverName, volume.getName(), brickName); - - addBrickToVolume(volume, serverName, brickDir, brickStatus); - return true; - } - return false; - } - - private void addBrickToVolume(Volume volume, String serverName, String brickDir, BRICK_STATUS status) { - //If brick directory has standard path, find and assign device name otherwise null - String stdBrickDirPattern = "^/export/.*/.*"; // e.g: /export/sdb/test - String deviceName = null; - if (Pattern.matches(stdBrickDirPattern, brickDir) ) { - deviceName = brickDir.split("/")[2].trim(); - } - volume.addBrick(new Brick(serverName, status, deviceName, brickDir)); - } - - // Do not throw exception, Gracefully handle as Offline brick. - private BRICK_STATUS getBrickStatus(String serverName, String volumeName, String brick){ - try { - ProcessResult output = getSshUtil().executeRemote(serverName, "get_brick_status.py" + " " + volumeName + " " + brick); - - if (output.isSuccess() && output.getOutput().equals(CoreConstants.ONLINE)) { - return BRICK_STATUS.ONLINE; - } else { - return BRICK_STATUS.OFFLINE; - } - } catch(Exception e) { // Particularly interested on ConnectionExecption, if the server is offline - return BRICK_STATUS.OFFLINE; - } - } - - private boolean readBrickGroup(String line) { - return extractToken(line, VOLUME_BRICKS_GROUP_PFX) != null; - } - - private boolean readOptionReconfigGroup(String line) { - return extractToken(line, VOLUME_OPTIONS_RECONFIG_PFX) != null; - } - - private boolean readOption(Volume volume, String line) { - if (line.matches("^[^:]*:.*$")) { - int index = line.indexOf(':'); - volume.setOption(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim()); - - if (line.substring(0, index).trim().equals(Volume.OPTION_NFS_DISABLE)) { - if (line.substring(index + 1, line.length()).trim().equals(GlusterConstants.ON)) { - volume.disableNFS(); - } else { - volume.enableNFS(); - } - } - - return true; - } - return false; - } - - public Volume getVolume(String volumeName, String knownServer) { - return parseVolumeInfo(getVolumeInfo(volumeName, knownServer)).get(0); - } - - public List getAllVolumes(String knownServer) { - return parseVolumeInfo(getVolumeInfo(knownServer)); - } - - private List parseVolumeInfo(String volumeInfoText) { - List volumes = new ArrayList(); - boolean isBricksGroupFound = false; - boolean isOptionReconfigFound = false; - Volume volume = null; - - for (String line : volumeInfoText.split(CoreConstants.NEWLINE)) { - String volumeName = extractToken(line, VOLUME_NAME_PFX); - if (volumeName != null) { - if (volume != null) { - volumes.add(volume); - } - - // prepare next volume to be read - volume = new Volume(); - volume.setName(volumeName); - isBricksGroupFound = isOptionReconfigFound = false; - continue; - } - - if (readVolumeType(volume, line)) - continue; - if (extractToken(line, VOLUME_NUMBER_OF_BRICKS) != null) { - readReplicaOrStripeCount(volume, line); - } - if (readVolumeStatus(volume, line)) - continue; - if (readTransportType(volume, line)) - continue; - if (readBrickGroup(line)) { - isBricksGroupFound = true; - continue; - } - - if (isBricksGroupFound) { - if (readBrick(volume, line)) { - continue; - } else { - isBricksGroupFound = false; - } - } - - if (readOptionReconfigGroup(line)) { - isOptionReconfigFound = true; - continue; - } - - if (isOptionReconfigFound) { - if (readOption(volume, line)) { - continue; - } else { - isOptionReconfigFound = false; - } - } - } - - if (volume != null) {// Adding the last volume parsed - volumes.add(volume); - } - - return volumes; - } - - public void addBricks(String volumeName, List bricks, String knownServer) { - StringBuilder command = new StringBuilder("gluster volume add-brick " + volumeName); - for (String brickDir : bricks) { - command.append(" " + brickDir); - } - - ProcessResult result = sshUtil.executeRemote(knownServer, command.toString()); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Error in volume [" + volumeName + "] add-brick [" + bricks + "]: " - + result); - } - } - - public String getLogLocation(String volumeName, String brickName, String knownServer) { - String command = "gluster volume log locate " + volumeName + " " + brickName; - ProcessResult result = sshUtil.executeRemote(knownServer, command); - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [" + command + "] failed with error: [" + result.getExitValue() - + "][" + result.getOutput() + "]"); - } - String output = result.getOutput(); - if (output.startsWith(VOLUME_LOG_LOCATION_PFX)) { - return output.substring(VOLUME_LOG_LOCATION_PFX.length()).trim(); - } - - throw new GlusterRuntimeException("Couldn't parse output of command [" + command + "]. Output [" + output - + "] doesn't start with prefix [" + VOLUME_LOG_LOCATION_PFX + "]"); - } - - public String getLogFileNameForBrickDir(String brickDir) { - String logFileName = brickDir; - if (logFileName.startsWith(File.separator)) { - logFileName = logFileName.replaceFirst(File.separator, ""); - } - logFileName = logFileName.replaceAll(File.separator, "-") + ".log"; - return logFileName; - } - - public Status removeBricks(String volumeName, List bricks, String knownServer) { - StringBuilder command = new StringBuilder("gluster --mode=script volume remove-brick " + volumeName); - for (String brickDir : bricks) { - command.append(" " + brickDir); - } - return new Status(sshUtil.executeRemote(knownServer, command.toString())); - } - - public void removeServer(String existingServer, String serverName) { - ProcessResult result = sshUtil.executeRemote(existingServer, "gluster --mode=script peer detach " + serverName); - if(!result.isSuccess()) { - throw new GlusterRuntimeException("Couldn't remove server [" + serverName + "]! Error: " + result); - } - } - - public TaskStatus checkRebalanceStatus(String serverName, String volumeName) { - String command = "gluster volume rebalance " + volumeName + " status"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - if (processResult.getOutput().trim().matches("^rebalance completed.*")) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else if(processResult.getOutput().trim().matches(".*in progress.*")) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - } else { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - taskStatus.setMessage(processResult.getOutput()); // Common - return taskStatus; - } - - public void stopRebalance(String serverName, String volumeName) { - String command = "gluster volume rebalance " + volumeName + " stop"; - ProcessResult processResult = sshUtil.executeRemote(serverName, command); - TaskStatus taskStatus = new TaskStatus(); - if (processResult.isSuccess()) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - taskStatus.setMessage(processResult.getOutput()); - } - } - - public TaskStatus getInitializingDeviceStatus(String serverName, String diskName) { - Object response = serverUtil.executeScriptOnServer(true, serverName, INITIALIZE_DISK_STATUS_SCRIPT + " " - + diskName, InitDiskStatusResponse.class); - - TaskStatus taskStatus = new TaskStatus(); - if (response instanceof Status) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - taskStatus.setMessage(((Status) response).getMessage()); - throw new GlusterRuntimeException(((Status) response).getMessage()); - } - - InitDiskStatusResponse initDiskStatusResponse = (InitDiskStatusResponse) response; - - if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.COMPLETED) { - taskStatus.setCode(Status.STATUS_CODE_SUCCESS); - } else if (initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.IN_PROGRESS) { - taskStatus.setCode(Status.STATUS_CODE_RUNNING); - taskStatus.setPercentCompleted(Math.round(initDiskStatusResponse.getCompletedBlocks() - / initDiskStatusResponse.getTotalBlocks() * 100)); - } else if(initDiskStatusResponse.getFormatStatus() == FORMAT_STATUS.NOT_RUNNING) { - taskStatus.setCode(Status.STATUS_CODE_FAILURE); - } - - taskStatus.setMessage(initDiskStatusResponse.getMessage()); - return taskStatus; - } - - public ProcessResult executeBrickMigration(String onlineServerName, String volumeName, String fromBrick, - String toBrick, String operation) { - String command = "gluster volume replace-brick " + volumeName + " " + fromBrick + " " + toBrick + " " + operation; - ProcessResult processResult = sshUtil.executeRemote(onlineServerName, command); - if (!processResult.isSuccess()) { - throw new GlusterRuntimeException(processResult.toString()); - } - return processResult; - } - - public static void main(String args[]) { - // List names = new GlusterUtil().getGlusterServerNames(); - // System.out.println(names); - List disks = new ArrayList(); - disks.add("server1:sda"); - disks.add("server1:sdb"); - new GlusterUtil().addBricks("Volume3", disks, "localhost"); - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java deleted file mode 100644 index dc88bf52..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/MemoryStatsFactory.java +++ /dev/null @@ -1,68 +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.gateway.utils; - -import java.util.List; - -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; - -/** - * - */ -@Component -public class MemoryStatsFactory extends AbstractStatsFactory { - - private static final String MEM_STATS_SCRIPT = "get_rrd_memory_details.py"; - - @Override - public String getStatsScriptName() { - return MEM_STATS_SCRIPT; - } - - @Override - public ServerStats fetchStats(String serverName, String period, String... args) { - ServerStats stats = super.fetchStats(serverName, period, args); - - // stats returned by rrd script contains five columns - user, free, cache, buffer, total - // out of this, the "user" memory includes cached and buffer. We remove them to get the - // actual memory used by "user" - for(ServerStatsRow row : stats.getRows()) { - List data = row.getUsageData(); - Double user = data.get(0); - Double free = data.get(1); - Double cache = data.get(2); - Double buffer = data.get(3); - Double total = data.get(4); - - Double actualUser = user - cache - buffer; - - // convert all figures from bytes to percentages - data.set(0, (actualUser * 100) / total); - data.set(1, (free * 100) / total); - data.set(2, (cache * 100) / total); - data.set(3, (buffer * 100) / total); - data.set(4, (total * 100) / total); - } - - return stats; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java deleted file mode 100644 index d3d47c58..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/NetworkStatsFactory.java +++ /dev/null @@ -1,123 +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.gateway.utils; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.NetworkInterface; -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; - -/** - * - */ -@Component -public class NetworkStatsFactory extends AbstractStatsFactory { - private static final Logger logger = Logger.getLogger(NetworkStatsFactory.class); - private static final String NETWORK_STATS_SCRIPT = "get_rrd_net_details.py"; - private int[][] dataCount; - - @Override - public String getStatsScriptName() { - return NETWORK_STATS_SCRIPT; - } - - @Override - protected ServerStats getFirstOnlineServerStats(List serverNames, String period, - boolean removeServerOnError, boolean removeOnlineServer) { - ServerStats firstOnlineServerStats = null; - for(int i = serverNames.size() - 1; i >= 0; i--) { - String serverName = serverNames.get(i); - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - try { - for(NetworkInterface networkInterface : server.getNetworkInterfaces()) { - ServerStats stats = fetchStats(serverName, period, networkInterface.getName()); - if(firstOnlineServerStats == null) { - firstOnlineServerStats = stats; - int rowCount = firstOnlineServerStats.getMetadata().getRowCount(); - int columnCount = firstOnlineServerStats.getMetadata().getLegend().size(); - dataCount = initDataCountArray(rowCount, columnCount); - } else { - addServerStats(stats, firstOnlineServerStats, dataCount); - } - } - - if(removeOnlineServer) { - serverNames.remove(serverName); - } - return firstOnlineServerStats; - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch stats from server [" + serverName + "]!", e); - if(removeServerOnError) { - serverNames.remove(serverName); - } - continue; - } - } - throw new GlusterRuntimeException("All servers offline!"); - } - - protected void aggregateStats(List serverNames, ServerStats aggregatedStats, String period) { - if(serverNames.isEmpty()) { - return; - } - - for (String serverName : serverNames) { - try { - Server server = new Server(serverName); - serverUtil.fetchServerDetails(server); - - for (NetworkInterface networkInterface : server.getNetworkInterfaces()) { - // fetch the stats and add to aggregated stats - addServerStats(fetchStats(serverName, period, networkInterface.getName()), aggregatedStats, dataCount); - } - } catch(Exception e) { - // server might be offline - continue with next one - logger.warn("Couldn't fetch Network stats from server [" + serverName + "]!", e); - continue; - } - } - - averageAggregatedStats(aggregatedStats, dataCount); - } - - @Override - public ServerStats fetchStats(String serverName, String period, String... args) { - ServerStats stats = super.fetchStats(serverName, period, args); - - // the data returned by rrd contains "bytes" transferred in the given time step. Update the stats object to represent KiB/s - int step = stats.getMetadata().getStep(); - for(ServerStatsRow row : stats.getRows()) { - List data = row.getUsageData(); - for (int i = 0; i < data.size(); i++) { - Double val = data.get(i); - data.set(i, val / 1024 / step); - } - } - - return stats; - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java deleted file mode 100644 index 91c7c81c..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/ServerUtil.java +++ /dev/null @@ -1,286 +0,0 @@ -/** - * ServerUtil.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.gateway.utils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.ServletContext; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.model.Server; -import com.gluster.storage.management.core.model.ServerStats; -import com.gluster.storage.management.core.model.ServerStatsRow; -import com.gluster.storage.management.core.model.Status; -import com.gluster.storage.management.core.response.GenericResponse; -import com.gluster.storage.management.core.utils.ProcessResult; -import com.gluster.storage.management.core.utils.ProcessUtil; - -@Component -public class ServerUtil { - @Autowired - ServletContext servletContext; - - @Autowired - private SshUtil sshUtil; - - @Autowired - private String appVersion; - - private static final Logger logger = Logger.getLogger(ServerUtil.class); - - private static final String SCRIPT_DIR = "scripts"; - private static final String SCRIPT_COMMAND = "python"; - private static final String REMOTE_SCRIPT_GET_DISK_FOR_DIR = "get_disk_for_dir.py"; - private static final String REMOTE_SCRIPT_GET_SERVER_DETAILS = "get_server_details.py"; - private static final String REMOTE_SCRIPT_BASE_DIR = "/opt/glustermg"; - private static final String REMOTE_SCRIPT_DIR_NAME = "backend"; - - public void setSshUtil(SshUtil sshUtil) { - this.sshUtil = sshUtil; - } - - public ProcessResult executeGlusterScript(boolean runInForeground, String scriptName, List arguments) { - List command = new ArrayList(); - - command.add(SCRIPT_COMMAND); - command.add(getScriptPath(scriptName)); - command.addAll(arguments); - return new ProcessUtil().executeCommand(runInForeground, command); - } - - private String getScriptPath(String scriptName) { - return servletContext.getRealPath(SCRIPT_DIR) + CoreConstants.FILE_SEPARATOR + scriptName; - } - - private String getRemoteScriptDir() { - return REMOTE_SCRIPT_BASE_DIR + File.separator + appVersion + File.separator + REMOTE_SCRIPT_DIR_NAME; - } - - /** - * Fetch details of the given server. The server name must be populated in the object before calling this method. - * - * @param server - * Server whose details are to be fetched - */ - public void fetchServerDetails(Server server) { - Object response = fetchServerDetails(server.getName()); - server.copyFrom((Server) response); // Update the details in object - server.setDisks(((Server) response).getDisks()); - } - - public String fetchHostName(String serverName) { - Object response = fetchServerDetails(serverName); - return ((Server) response).getName(); - } - - private Object fetchServerDetails(String serverName) { - // fetch standard server details like cpu, disk, memory details - Object response = executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_SERVER_DETAILS, Server.class); - if (response instanceof Status) { - throw new GlusterRuntimeException(((Status) response).getMessage()); - } - return response; - } - - /** - * Executes given script on given server. Since the remote server may contain multiple versions of backend, this - * method will invoke the script present in directory of same version as the gateway. - * - * @param runInForeground - * @param serverName - * @param scriptWithArgs - * The script name followed by arguments to be passed. Note that the script name should not contain path - * as it will be automatically identified by the method. - * @param expectedClass - * Class of the object expected from script execution - * @return Object of the expected class from remote execution of the command. In case the remote execution fails - * ungracefully, an object of class {@link Status} will be returned. - */ - public Object executeScriptOnServer(boolean runInForeground, String serverName, String scriptWithArgs, - @SuppressWarnings("rawtypes") Class expectedClass) { - return executeOnServer(runInForeground, serverName, getRemoteScriptDir() + File.separator + scriptWithArgs, expectedClass); - } - - /** - * Executes given command on given server - * - * @param runInForeground - * @param serverName - * @param commandWithArgs - * @param expectedClass - * Class of the object expected from script execution - * @return Object of the expected class from remote execution of the command. In case the remote execution fails - * ungracefully, an object of class {@link Status} will be returned. - */ - @SuppressWarnings("rawtypes") - public Object executeOnServer(boolean runInForeground, String serverName, String commandWithArgs, - Class expectedClass) { - try { - String output = executeOnServer(serverName, commandWithArgs); - - // In case the script execution exits ungracefully, the agent would return a GenericResponse. - // hence pass last argument as true to try GenericResponse unmarshalling in such cases. - Object response = unmarshal(expectedClass, output, expectedClass != GenericResponse.class); - if (expectedClass != GenericResponse.class && response instanceof GenericResponse) { - // expected class was not GenericResponse, but that's what we got. This means the - // script failed ungracefully. Extract and return the status object from the response - return ((GenericResponse) response).getStatus(); - } - return response; - } catch (RuntimeException e) { - // Except for connection exception, wrap any other exception in the a object and return it. - if (e instanceof ConnectionException) { - throw e; - } else { - // error during unmarshalling. return status with error from exception. - return new Status(e); - } - } - } - - private String executeOnServer(String serverName, String commandWithArgs) { - ProcessResult result = sshUtil.executeRemote(serverName, commandWithArgs); - - if (!result.isSuccess()) { - throw new GlusterRuntimeException("Command [" + commandWithArgs + "] failed on [" + serverName - + "] with error [" + result.getExitValue() + "][" + result.getOutput() + "]"); - } - return result.getOutput(); - } - - // This is the old executeOnServer that used socket communication. - // We can keep it commented for the time being. - // private String executeOnServerUsingSocket(String serverName, String commandWithArgs) { - // try { - // InetAddress address = InetAddress.getByName(serverName); - // Socket connection = new Socket(address, 50000); - // - // PrintWriter writer = new PrintWriter(connection.getOutputStream(), true); - // writer.println(commandWithArgs); - // writer.println(); // empty line means end of request - // - // InputStream inputStream = connection.getInputStream(); - // int available = inputStream.available(); - // - // StringBuffer output = new StringBuffer(); - // if( available > 0 ) { - // // This happens when PeerAgent sends complete file - // byte[] responseData = new byte[available]; - // inputStream.read(responseData); - // output.append(new String(responseData, "UTF-8")); - // } else { - // // This happens in case of normal XML response from PeerAgent - // BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); - // - // String line; - // while (!(line = reader.readLine()).trim().isEmpty()) { - // output.append(line + CoreConstants.NEWLINE); - // } - // } - // connection.close(); - // - // return output.toString(); - // } catch (Exception e) { - // throw new GlusterRuntimeException("Error during remote execution: [" + e.getMessage() + "]"); - // } - // } - - public void getFileFromServer(String serverName, String remoteFileName, String localDirName) { - sshUtil.getFile(serverName, remoteFileName, localDirName); - } - - /** - * Unmarshals given input string into object of given class - * - * @param expectedClass - * Class whose object is expected - * @param input - * Input string - * @param tryGenericResponseOnFailure - * If true, and if the unmarshalling fails for given class, another unmarshalling will be attempted with - * class {@link GenericResponse}. If this also fails, a status object with exception message is created - * and returned. - * @return Object of given expected class, or a status object in case first unmarshalling fails. - */ - @SuppressWarnings("rawtypes") - private Object unmarshal(Class expectedClass, String input, boolean tryGenericResponseOnFailure) { - try { - // create JAXB context and instantiate marshaller - JAXBContext context = JAXBContext.newInstance(expectedClass); - Unmarshaller um = context.createUnmarshaller(); - return um.unmarshal(new ByteArrayInputStream(input.getBytes())); - } catch (JAXBException e) { - if (tryGenericResponseOnFailure) { - // unmarshalling failed. try to unmarshal a GenericResponse object - return unmarshal(GenericResponse.class, input, false); - - } - return new Status(Status.STATUS_CODE_FAILURE, "Error during unmarshalling string [" + input - + "] for class [" + expectedClass.getName() + ": [" + e.getMessage() + "]"); - } - } - - /** - * @param serverName - * Server on which the directory is present - * @param brickDir - * Directory whose disk is to be fetched - * @return Status object containing the disk name, or error message in case the remote script fails. - */ - public Status getDiskForDir(String serverName, String brickDir) { - return (Status) executeScriptOnServer(true, serverName, REMOTE_SCRIPT_GET_DISK_FOR_DIR + " " + brickDir, Status.class); - } - - public static void main(String[] args) { -// ServerStats stats = new ServerUtil().fetchCPUUsageData("s1", "1d"); -// for(ServerStatsRow row : stats.getRows()) { -// System.out.println(row.getUsageData().get(2)); -// } -// JAXBContext context; -// try { -// context = JAXBContext.newInstance(ServerStats.class); -// Marshaller m = context.createMarshaller(); -// ByteArrayOutputStream out = new ByteArrayOutputStream(); -// m.marshal(stats, out); -// ServerStats stats1 = (ServerStats)new ServerUtil().unmarshal(ServerStats.class, out.toString(), false); -// for(ServerStatsRow row : stats1.getRows()) { -// System.out.println(row.getUsageData().get(2)); -// } -// } catch (JAXBException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java deleted file mode 100644 index 39dd42f9..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/SshUtil.java +++ /dev/null @@ -1,388 +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.gateway.utils; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Arrays; - -import org.apache.log4j.Logger; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import ch.ethz.ssh2.ChannelCondition; -import ch.ethz.ssh2.Connection; -import ch.ethz.ssh2.SCPClient; -import ch.ethz.ssh2.Session; -import ch.ethz.ssh2.StreamGobbler; - -import com.gluster.storage.management.core.constants.CoreConstants; -import com.gluster.storage.management.core.exceptions.ConnectionException; -import com.gluster.storage.management.core.exceptions.GlusterRuntimeException; -import com.gluster.storage.management.core.utils.FileUtil; -import com.gluster.storage.management.core.utils.LRUCache; -import com.gluster.storage.management.core.utils.ProcessResult; - -/** - * - */ -@Component -public class SshUtil { - private static final String TEMP_DIR = "/tmp/"; - public static final String SSH_AUTHORIZED_KEYS_DIR_LOCAL = "/opt/glustermg/keys/"; - public static final String SSH_AUTHORIZED_KEYS_DIR_REMOTE = "/root/.ssh/"; - private static final String SSH_AUTHORIZED_KEYS_FILE = "authorized_keys"; - private static final String SSH_AUTHORIZED_KEYS_PATH_REMOTE = SSH_AUTHORIZED_KEYS_DIR_REMOTE + SSH_AUTHORIZED_KEYS_FILE; - public static final File PRIVATE_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa"); - public static final File PUBLIC_KEY_FILE = new File(SSH_AUTHORIZED_KEYS_DIR_LOCAL + "id_rsa.pub"); -// private static final String SCRIPT_DISABLE_SSH_PASSWORD_AUTH = "disable-ssh-password-auth.sh"; - private static final String PRIVATE_KEY_PASSPHRASE = "gluster"; - private LRUCache sshConnCache = new LRUCache(10); - - // TODO: Make user name configurable - private static final String USER_NAME = "root"; - // TODO: Make default password configurable - private static final String DEFAULT_PASSWORD = "syst3m"; - - private static final Logger logger = Logger.getLogger(SshUtil.class); - - @Autowired - private Integer sshConnectTimeout; - @Autowired - private Integer sshKexTimeout; - @Autowired - private Integer sshExecTimeout; - - public boolean hasDefaultPassword(String serverName) { - try { - getConnectionWithPassword(serverName); - return true; - } catch(ConnectionException e) { - return false; - } - } - - public boolean isPublicKeyInstalled(String serverName) { - try { - getConnection(serverName); - return true; - } catch(ConnectionException e) { - return false; - } - } - - public void getFile(String serverName, String remoteFile, String localDir) { - try { - Connection conn = getConnection(serverName); - SCPClient scpClient = new SCPClient(conn); - scpClient.get(remoteFile, localDir); - } catch (IOException e) { - throw new GlusterRuntimeException("Error while fetching file [" + remoteFile + "] from server [" - + serverName + "]", e); - } - } - - public synchronized void installPublicKey(String serverName) { - Connection conn = getConnectionWithPassword(serverName); - SCPClient scpClient = new SCPClient(conn); - - // delete file if it exists - File localTempFile = new File(TEMP_DIR + SSH_AUTHORIZED_KEYS_FILE); - if(localTempFile.exists()) { - localTempFile.delete(); - } - try { - // get authorized_keys from server - scpClient.get(SSH_AUTHORIZED_KEYS_PATH_REMOTE, TEMP_DIR); - } catch (IOException e) { - // file doesn't exist. it will get created. - } - - byte[] publicKeyData; - try { - publicKeyData = FileUtil.readFileAsByteArray(PUBLIC_KEY_FILE); - } catch (Exception e) { - throw new GlusterRuntimeException("Couldn't load public key file [" + PUBLIC_KEY_FILE + "]", e); - } - - try { - // append it - FileOutputStream outputStream = new FileOutputStream(localTempFile, true); - outputStream.write(CoreConstants.NEWLINE.getBytes()); - outputStream.write(publicKeyData); - outputStream.close(); - } catch (Exception e) { - throw new GlusterRuntimeException("Couldnt append file [" + localTempFile + "] with public key!", e); - } - - try { - scpClient.put(localTempFile.getAbsolutePath(), SSH_AUTHORIZED_KEYS_FILE, SSH_AUTHORIZED_KEYS_DIR_REMOTE, "0600"); - } catch (IOException e) { - throw new GlusterRuntimeException("Couldn't add public key to server [" + serverName + "]", e); - } - - // It was decided NOT to disable password login as this may not be acceptable in a bare-metal environment - // disableSshPasswordLogin(serverName, scpClient); - } - -// private void disableSshPasswordLogin(String serverName, SCPClient scpClient) { -// ProcessResult result = executeRemote(serverName, SCRIPT_DISABLE_SSH_PASSWORD_AUTH); -// if(!result.isSuccess()) { -// throw new GlusterRuntimeException("Couldn't disable SSH password authentication on [" + serverName -// + "]. Error: " + result); -// } -// } - - private Connection getConnectionWithPassword(String serverName) { - Connection conn = createConnection(serverName); - authenticateWithPassword(conn); - return conn; - } - - private synchronized Connection getConnection(String serverName) { - Connection conn = sshConnCache.get(serverName); - if (conn != null) { - return conn; - } - - conn = createConnection(serverName); - authenticateWithPublicKey(conn); - sshConnCache.put(serverName, conn); - return conn; - } - - private void authenticateWithPublicKey(Connection conn) { - try { - if (!supportsPublicKeyAuthentication(conn)) { - throw new ConnectionException("Public key authentication not supported on [" + conn.getHostname() - + "]"); - } - - if (!conn.authenticateWithPublicKey(USER_NAME, PRIVATE_KEY_FILE, PRIVATE_KEY_PASSPHRASE)) { - throw new ConnectionException("SSH Authentication (public key) failed for server [" - + conn.getHostname() + "]"); - } - } catch (IOException e) { - e.printStackTrace(); - throw new ConnectionException("Exception during SSH authentication (public key) for server [" - + conn.getHostname() + "]", e); - } - } - - private void authenticateWithPassword(Connection conn) { - try { - if (!supportsPasswordAuthentication(conn)) { - throw new ConnectionException("Password authentication not supported on [" + conn.getHostname() - + "]"); - } - - if (!conn.authenticateWithPassword(USER_NAME, DEFAULT_PASSWORD)) { - throw new ConnectionException("SSH Authentication (password) failed for server [" - + conn.getHostname() + "]"); - } - } catch (IOException e) { - e.printStackTrace(); - throw new ConnectionException("Exception during SSH authentication (password) for server [" - + conn.getHostname() + "]", e); - } - } - - private boolean supportsPasswordAuthentication(Connection conn) throws IOException { - return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("password"); - } - - private boolean supportsPublicKeyAuthentication(Connection conn) throws IOException { - return Arrays.asList(conn.getRemainingAuthMethods(USER_NAME)).contains("publickey"); - } - - private Connection createConnection(String serverName) { - Connection conn; - conn = new Connection(serverName); - try { - conn.connect(null, sshConnectTimeout, sshKexTimeout); - } catch (IOException e) { - logger.error("Couldn't establish SSH connection with server [" + serverName + "]", e); - throw new ConnectionException("Exception while creating SSH connection with server [" + serverName + "]", e); - } - return conn; - } - - private boolean wasTerminated(int condition) { - return ((condition | ChannelCondition.EXIT_SIGNAL) == condition); - } - - private boolean hasErrors(int condition, Session session) { - return (hasErrorStream(condition) || (exitedGracefully(condition) && exitedWithError(session))); - } - - private boolean timedOut(int condition) { - return (condition == ChannelCondition.TIMEOUT); - } - - private boolean exitedWithError(Session session) { - return session.getExitStatus() != ProcessResult.SUCCESS; - } - - private boolean exitedGracefully(int condition) { - return (condition | ChannelCondition.EXIT_STATUS) == condition; - } - - private boolean hasErrorStream(int condition) { - return (condition | ChannelCondition.STDERR_DATA) == condition; - } - - private ProcessResult executeCommand(Connection sshConnection, String command) { - try { - Session session = sshConnection.openSession(); - BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(new StreamGobbler( - session.getStdout()))); - BufferedReader stderrReader = new BufferedReader(new InputStreamReader(new StreamGobbler( - session.getStderr()))); - session.execCommand(command); - ProcessResult result = getResultOfExecution(session, stdoutReader, stderrReader); - session.close(); - return result; - } catch (IOException e) { - String errMsg = "Exception while executing command [" + command + "] on [" + sshConnection.getHostname() - + "]"; - logger.error(errMsg, e); - throw new GlusterRuntimeException(errMsg, e); - } - } - - private ProcessResult getResultOfExecution(Session session, BufferedReader stdoutReader, BufferedReader stderrReader) { - // Wait for program to come out either - // a) gracefully with an exit status, OR - // b) because of a termination signal - // c) command takes to long to exit (timeout) - int condition = session.waitForCondition(ChannelCondition.EXIT_SIGNAL | ChannelCondition.EXIT_STATUS, - sshExecTimeout); - StringBuilder output = new StringBuilder(); - - try { - if(!timedOut(condition)) { - readFromStream(stdoutReader, output); - if (hasErrors(condition, session)) { - readFromStream(stderrReader, output); - } - } - - return prepareProcessResult(session, condition, output.toString().trim()); - } catch (IOException e) { - String errMsg = "Error while reading output stream from SSH connection!"; - logger.error(errMsg, e); - return new ProcessResult(ProcessResult.FAILURE, errMsg); - } - } - - private ProcessResult prepareProcessResult(Session session, int condition, String output) { - ProcessResult result = null; - - if (wasTerminated(condition)) { - result = new ProcessResult(ProcessResult.FAILURE, output); - } else if (timedOut(condition)) { - result = new ProcessResult(ProcessResult.FAILURE, "Command timed out!"); - } else if (hasErrors(condition, session)) { - Integer exitStatus = session.getExitStatus(); - int statusCode = (exitStatus == null ? ProcessResult.FAILURE : exitStatus); - result = new ProcessResult(statusCode, output); - } else { - result = new ProcessResult(ProcessResult.SUCCESS, output); - } - - return result; - } - - private void readFromStream(BufferedReader streamReader, StringBuilder output) throws IOException { - while (true) { - String line = streamReader.readLine(); - if (line == null) { - break; - } - output.append(line + CoreConstants.NEWLINE); - } - } - - /** - * Executes given command on remote machine using password authentication - * - * @param serverName - * @param command - * @return Result of remote execution - */ - public ProcessResult executeRemoteWithPassword(String serverName, String command) { - return executeCommand(getConnectionWithPassword(serverName), command); - } - - private ProcessResult executeRemoteWithPubKey(String serverName, String command) { - try { - return executeCommand(getConnection(serverName), command); - } catch(GlusterRuntimeException e) { - Throwable cause = e.getCause(); - if(cause != null && cause instanceof IOException) { - // cached ssh connection might have gone bad. - // remove it and try with a new one - sshConnCache.remove(serverName); - return executeCommand(getConnection(serverName), command); - } else { - throw e; - } - } - } - - /** - * Executes given command on remote machine using public key authentication - * - * @param serverName - * @param command - * @return Result of remote execution - */ - public ProcessResult executeRemote(String serverName, String command) { - try { - return executeRemoteWithPubKey(serverName, command); - } catch(ConnectionException e) { - // Couldn't connect with public key. Try with default password. - return executeRemoteWithPassword(serverName, command); - } - } - - /** - * Checks if public key of management gateway is configured on given server - * - * @param serverName - * @return true if public key is configured, else false - */ - public boolean isPublicKeySetup(String serverName) { - try { - getConnection(serverName); - return true; - } catch (Exception e) { - return false; - } - } - - public void cleanup() { - for (Connection conn : sshConnCache.values()) { - conn.close(); - } - } -} diff --git a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java b/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java deleted file mode 100644 index 09851367..00000000 --- a/src/com.gluster.storage.management.server/src/com/gluster/storage/management/gateway/utils/StatsFactory.java +++ /dev/null @@ -1,31 +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.gateway.utils; - -import java.util.List; - -import com.gluster.storage.management.core.model.ServerStats; - -/** - * - */ -public interface StatsFactory { - public ServerStats fetchStats(String serverName, String period, String...args); - public ServerStats fetchAggregatedStats(List serverName, String period); -} diff --git a/src/com.gluster.storage.management.server/src/log4j.properties b/src/com.gluster.storage.management.server/src/log4j.properties deleted file mode 100644 index 18e2e8b1..00000000 --- a/src/com.gluster.storage.management.server/src/log4j.properties +++ /dev/null @@ -1,19 +0,0 @@ -log4j.rootLogger=INFO, CONSOLE - -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.immediateFlush=true -log4j.appender.CONSOLE.target=System.out -log4j.appender.CONSOLE.threshold=DEBUG -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=%d{dd MMM, yyyy HH:mm:ss} %p: %c %t - %m%n - -log4j.appender.R=org.apache.log4j.RollingFileAppender -log4j.appender.R.File=/var/log/glustermg/glustermg.log -log4j.appender.R.MaxFileSize=10MB -log4j.appender.R.MaxBackupIndex=10 -log4j.appender.R.layout=org.apache.log4j.PatternLayout -log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n - -log4j.logger.org=ERROR -log4j.logger.com=ERROR -log4j.logger.com.gluster=DEBUG \ No newline at end of file diff --git a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml b/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml deleted file mode 100644 index c89eb2f0..00000000 --- a/src/com.gluster.storage.management.server/src/spring/gluster-server-base.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - com.gluster.storage.management.gateway.data.ClusterInfo - - - - - - com.gluster.storage.management.gateway.data.ServerInfo - - - - - - - - - - - \ No newline at end of file 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 deleted file mode 100644 index abcd8c05..00000000 --- a/src/com.gluster.storage.management.server/src/spring/gluster-server-security.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file -- cgit