diff options
author | Bala.FA <bala@gluster.com> | 2011-08-03 19:20:58 +0530 |
---|---|---|
committer | Bala.FA <bala@gluster.com> | 2011-08-03 19:41:49 +0530 |
commit | 8c798649cd585075889e44a7934f75c7047846c9 (patch) | |
tree | ca18b671c21fafc0a7eb28c76125c394d797dbbf | |
parent | 04c07646fa7d429eaca68c3b5166952fd92abf12 (diff) |
Enhancements in multicast discovery services and run level init script is added
Signed-off-by: Bala.FA <bala@gluster.com>
7 files changed, 268 insertions, 152 deletions
diff --git a/build/glustermg.spec b/build/glustermg.spec index af8f8f1f..8351879f 100644 --- a/build/glustermg.spec +++ b/build/glustermg.spec @@ -25,6 +25,8 @@ Requires: wget %package backend Summary: %{product_family} server side backend tools Group: System Environment/Base +Requires(post): /sbin/chkconfig +Requires(preun): /sbin/chkconfig Requires: python >= 2.4.3 Requires: perl >= 5.8.8 Requires: rrdtool-perl >= 1.2.27 @@ -52,6 +54,10 @@ rm -f $RPM_BUILD_ROOT/glustermg.war.tar.gz mkdir -p $RPM_BUILD_ROOT/opt/glustermg/%{release_version}/backend mkdir -p $RPM_BUILD_ROOT/var/lib/rrd cp -pa gmg-scripts/* $RPM_BUILD_ROOT/opt/glustermg/%{release_version}/backend +%{__install} -d -m0755 %{buildroot}%{_sbindir} +%{__install} -d -m0755 %{buildroot}%{_initrddir} +ln -sf /opt/glustermg/%{release_version}/backend/multicast-discoverd.py %{buildroot}%{_sbindir}/multicast-discoverd +%{__install} -p -m0755 gmg-scripts/multicast-discoverd.init.d %{buildroot}%{_initrddir}/multicast-discoverd %post chown -R tomcat:tomcat /opt/glustermg /var/log/glustermg @@ -105,6 +111,13 @@ fi if ! grep -q rrd_net.pl /etc/crontab; then echo '*/5 * * * * root /opt/glustermg/%{release_version}/backend/rrd_net.pl' >> /etc/crontab fi +/sbin/chkconfig --add multicast-discoverd +/sbin/chkconfig --level 345 multicast-discoverd on + +%preun backend +if [ "$1" = 0 ] ; then + /sbin/chkconfig --del multicast-discoverd +fi %clean @@ -114,6 +127,8 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root,0755) /opt/glustermg/%{release_version}/backend /var/lib/rrd +%{_sbindir}/multicast-discoverd +%{_initrddir}/multicast-discoverd %files %defattr(-,root,root,0755) diff --git a/src/com.gluster.storage.management.gateway.scripts/src/Globals.py b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py index f8a07c25..d5cb1ae0 100644 --- a/src/com.gluster.storage.management.gateway.scripts/src/Globals.py +++ b/src/com.gluster.storage.management.gateway.scripts/src/Globals.py @@ -16,7 +16,15 @@ # <http://www.gnu.org/licenses/>. MULTICAST_GROUP = '224.224.1.1' -MULTICAST_PORT = 5353 +MULTICAST_PORT = 24729 +GLUSTER_PROBE_STRING = "GLUSTERPROBE" +GLUSTER_PROBE_VERSION = "1.0.0" +DEFAULT_BUFSIZE = 1024 +SERVER_PORT = 24731 +DEFAULT_BACKLOG = 5 +DEFAULT_TIMEOUT = 5 +DEFAULT_ID_LENGTH = 16 + GLUSTER_PLATFORM_VERSION = "3.2" ## System configuration constants diff --git a/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.init.d b/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.init.d new file mode 100755 index 00000000..7cfbe44a --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.init.d @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com> +# This file is part of Gluster Management Gateway. +# +# chkconfig: - 85 15 +# description: multicast discovery service +# processname: multicast-discoverd +# pidfile: /var/run/multicast-discoverd.pid + +# Source function library. + +. /etc/init.d/functions + +case "$1" in + start) + echo -n "Starting multicast-discoverd:" + daemon multicast-discoverd + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/multicast-discoverd + ;; + stop) + echo -n "Shutting down multicast-discoverd:" + killproc multicast-discoverd + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/multicast-discoverd + ;; + restart) + $0 stop + $0 start + RETVAL=$? + ;; + status) + status multicast-discoverd + RETVAL=$? + ;; + reload) + killproc multicast-discoverd -HUP + RETVAL=$? + echo + ;; + *) + echo $"Usage: $0 {start|stop|restart|status|reload}" + exit 1 +esac + +exit $RETVAL diff --git a/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.py b/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.py new file mode 100755 index 00000000..dea08c2d --- /dev/null +++ b/src/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.py @@ -0,0 +1,105 @@ +#!/usr/bin/python +# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com> +# This file is part of Gluster Management Gateway. +# + +import os +import sys +p1 = os.path.abspath(os.path.dirname(sys.argv[0])) +p2 = "%s/common" % os.path.dirname(p1) +if not p1 in sys.path: + sys.path.append(p1) +if not p2 in sys.path: + sys.path.append(p2) +import socket +import struct +import signal +import time +import Utils +import Globals + +PID_FILE = "/var/run/multicast-discoverd.pid" +GLUSTERD_UUID = "NA" + +def exitHandler(signum, frame): + try: + if os.path.exists(PID_FILE): + os.unlink(PID_FILE) + except OSError, e: + Utils.log("Failed to remove PID file %s: %s" % (PID_FILE, str(e))) + sys.exit(0) + + +def updateGlusterdUuid(signum, frame): + try: + fp = open("/etc/glusterd/glusterd.info") + content = fp.read() + fp.close() + for line in content.strip().split(): + if line.startswith("UUID="): + GLUSTERD_UUID = line.split("=")[1] + break + except IOError, e: + Utils.log("failed to read file /etc/glusterd/glusterd.info: %s" % str(e)) + GLUSTERD_UUID = "NA" + + +def isInPeer(): + status = Utils.runCommand("gluster peer status", output=True) + if status["Status"] == 0: + if status["Stdout"].strip().upper() != "NO PEERS PRESENT": + return True + return False + + +def main(): + if os.path.exists(PID_FILE): + sys.stderr.write("fatal: PID file %s exists\n" % PID_FILE) + sys.exit(-1) + if not Utils.daemonize(): + sys.stderr.write("fatal: unable to run as daemon\n") + sys.exit(-1) + try: + fp = open(PID_FILE, "w") + fp.write("%s\n" % os.getpid()) + fp.close() + except IOError, e: + Utils.log("failed to create PID file %s: %s" % (PID_FILE, str(e))) + sys.exit(1) + + updateGlusterdUuid(None, None) + + signal.signal(signal.SIGINT, exitHandler) + signal.signal(signal.SIGTERM, exitHandler) + signal.signal(signal.SIGHUP, exitHandler) + + multicastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + multicastSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + multicastSocket.bind(('', Globals.MULTICAST_PORT)) + multicastSocket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, + struct.pack("4sl", socket.inet_aton(Globals.MULTICAST_GROUP), + socket.INADDR_ANY)) + + while True: + request = multicastSocket.recvfrom(Globals.DEFAULT_BUFSIZE) + if not request: + continue + #print "received [%s] from %s" % (request[0], request[1]) + tokens = request[0].strip().split(",") + if len(tokens) != 3: + continue + if tokens[0] != Globals.GLUSTER_PROBE_STRING: + continue + if isInPeer(): + continue + + time.sleep(0.2) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((request[1][0], Globals.SERVER_PORT)) + sock.send("%s,%s,%s,%s,%s,%s\n" % (tokens[0], tokens[1], tokens[2], socket.gethostname(), socket.getfqdn(), GLUSTERD_UUID)) + sock.close() + 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 deleted file mode 100644 index ae391b4b..00000000 --- a/src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com> -# 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 -# <http://www.gnu.org/licenses/>. - -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("<response><servername>%s</servername><time>%s</time></response>" % (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/WebContent/scripts/Globals.py b/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py index f8a07c25..89d3d098 100644 --- a/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py +++ b/src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py @@ -16,7 +16,15 @@ # <http://www.gnu.org/licenses/>. MULTICAST_GROUP = '224.224.1.1' -MULTICAST_PORT = 5353 +MULTICAST_PORT = 24729 +GLUSTER_PROBE_STRING = "GLUSTERPROBE" +GLUSTER_PROBE_VERSION = "1.0.0" +DEFAULT_BUFSIZE = 1024 +SERVER_PORT = 24731 +DEFAULT_BACKLOG = 5 +DEFAULT_TIMEOUT = 3 +DEFAULT_ID_LENGTH = 16 + GLUSTER_PLATFORM_VERSION = "3.2" ## System configuration constants 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 index 3c281f34..3c0dfcc4 100755 --- 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 @@ -1,20 +1,7 @@ #!/usr/bin/python -# Copyright (C) 2009 Gluster, Inc. <http://www.gluster.com> -# 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 -# <http://www.gnu.org/licenses/>. +# Copyright (C) 2011 Gluster, Inc. <http://www.gluster.com> +# This file is part of Gluster Management Gateway. +# import os import sys @@ -25,73 +12,92 @@ if not p1 in sys.path: if not p2 in sys.path: sys.path.append(p2) import socket +import select import signal -import struct -import syslog -import Globals -import time +import random +import string 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("<request><name>ServerDiscovery</name><time>%s</time></request>" % (sendtime), (multiCastGroup, port)) - - try: - while True: - response = socketReceive.recvfrom(200) - if not response: +import Globals + +running = True + + +def exitHandler(signum, frame): + running = False + + +def sendMulticastRequest(idString): + multicastSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) + multicastSocket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2) + multicastSocket.sendto("%s,%s,%s\n" % (Globals.GLUSTER_PROBE_STRING, Globals.GLUSTER_PROBE_VERSION, idString), + (Globals.MULTICAST_GROUP, Globals.MULTICAST_PORT)) + return multicastSocket + + +def openServerSocket(): + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.bind(('', Globals.SERVER_PORT)) + server.listen(Globals.DEFAULT_BACKLOG) + return server + + +def main(): + signal.signal(signal.SIGINT, exitHandler) + signal.signal(signal.SIGTERM, exitHandler) + signal.signal(signal.SIGALRM, exitHandler) + + idString = ''.join(random.choice(string.ascii_lowercase + + string.ascii_uppercase + + string.digits) for x in range(Globals.DEFAULT_ID_LENGTH)) + + multicastSocket = sendMulticastRequest(idString) + + serverInfoDict = {} + serverSocket = openServerSocket() + rlist = [serverSocket] + signal.alarm(Globals.DEFAULT_TIMEOUT) + while running: + try: + ilist,olist,elist = select.select(rlist, [], [], 0.25) + except select.error, e: + break + for sock in ilist: + # handle new connection + if sock == serverSocket: + clientSocket, address = serverSocket.accept() + #print "connection from %s on %s" % (address, clientSocket) + rlist.append(clientSocket) continue - dom = XDOM() - dom.parseString(response[0]) - if not dom: + + # handle all other sockets + data = sock.recv(Globals.DEFAULT_BUFSIZE) + if not data: + #print "closing socket %s" % sock + sock.close() + rlist.remove(sock) + tokens = data.strip().split(",") + if len(tokens) != 6: continue - if dom.getTextByTagRoute("request.name"): + if not (tokens[0] == Globals.GLUSTER_PROBE_STRING and \ + tokens[1] == Globals.GLUSTER_PROBE_VERSION and \ + tokens[2] == idString): 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 + serverInfoDict[tokens[3]] = [tokens[4], tokens[5]] + #print "closing socket %s" % sock + sock.close() + rlist.remove(sock) + + for sock in rlist: + sock.close() + + for k, v in serverInfoDict.iteritems(): + if v[0]: + print v[0] + else: + print k -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() |