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