summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBala.FA <bala@gluster.com>2011-08-03 19:20:58 +0530
committerBala.FA <bala@gluster.com>2011-08-03 19:41:49 +0530
commit8c798649cd585075889e44a7934f75c7047846c9 (patch)
treeca18b671c21fafc0a7eb28c76125c394d797dbbf
parent04c07646fa7d429eaca68c3b5166952fd92abf12 (diff)
Enhancements in multicast discovery services and run level init script is added
Signed-off-by: Bala.FA <bala@gluster.com>
-rw-r--r--build/glustermg.spec15
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/Globals.py10
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.init.d48
-rwxr-xr-xsrc/com.gluster.storage.management.gateway.scripts/src/multicast-discoverd.py105
-rw-r--r--src/com.gluster.storage.management.gateway.scripts/src/multicast_response.py74
-rw-r--r--src/com.gluster.storage.management.gateway/WebContent/scripts/Globals.py10
-rwxr-xr-xsrc/com.gluster.storage.management.gateway/WebContent/scripts/multicast-discover-servers.py158
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()