use threading for the webserver

This commit is contained in:
2016-01-04 22:27:05 +01:00
parent 4733f10007
commit 6929777ac6
+108 -79
View File
@@ -2,7 +2,7 @@
# $Id: hbd,v 1.38 2013/07/14 02:25:05 andreas Exp $ # $Id: hbd,v 1.38 2013/07/14 02:25:05 andreas Exp $
# Wait for heartbeat messages and act on them (or their absence) # Wait for heartbeat messages and act on them (or their absence)
# #
VER = 1.62 VER = 2.00
import time import time
import os import os
@@ -12,6 +12,7 @@ import socket
import atexit import atexit
import select import select
import SocketServer import SocketServer
import BaseHTTPServer
import getopt import getopt
import signal import signal
import cPickle import cPickle
@@ -19,6 +20,7 @@ import smtplib
import traceback import traceback
import urllib import urllib
import httplib import httplib
import threading
from subprocess import Popen, STDOUT, PIPE from subprocess import Popen, STDOUT, PIPE
@@ -62,11 +64,8 @@ def handler(signum, frame):
if verbose: if verbose:
sys.stderr.write("NOT runing signal: %s running: %d" % (sig, running)) sys.stderr.write("NOT runing signal: %s running: %d" % (sig, running))
sys.exit(2) sys.exit(2)
# signal.signal(sig, handler)
if verbose: if verbose:
sys.stderr.write("signal: %s running: %s frame: %s" % (sig, running, frame)) sys.stderr.write("signal: %s running: %s frame: %s" % (sig, running, frame))
running = False
# sys.exit(0)
def shortname(name): def shortname(name):
@@ -168,8 +167,7 @@ def email(s, msg):
body = "To: %s\nFrom: %s\nSubject: %s\nDate: %s\n\n%s" % (toaddrs[0], fromaddr, subj, date, msg) body = "To: %s\nFrom: %s\nSubject: %s\nDate: %s\n\n%s" % (toaddrs[0], fromaddr, subj, date, msg)
try: try:
server = smtplib.SMTP(SMTPSERVER) server = smtplib.SMTP(SMTPSERVER)
if DEBUG > 0: if DEBUG > 0: server.set_debuglevel(1)
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, body) server.sendmail(fromaddr, toaddrs, body)
except smtplib.SMTPRecipientsRefused, errs: except smtplib.SMTPRecipientsRefused, errs:
log("cannot send email: %s\n" % (errs)) log("cannot send email: %s\n" % (errs))
@@ -202,7 +200,7 @@ def pushover(msg):
# nsupdate: set the DNS A record for a fqdn # nsupdate: set the DNS A record for a fqdn
# return: None if ok, else error text # return: None if ok, else error text
def nsupdate(hostname, newip): def nsupdate(hostname, newip):
D = {} u = {}
D['domain'] = 'dy.wapanafa.org' D['domain'] = 'dy.wapanafa.org'
D['fqdn'] = '%s.dy.wapanafa.org' % hostname D['fqdn'] = '%s.dy.wapanafa.org' % hostname
D['dnsttl'] = '5' D['dnsttl'] = '5'
@@ -278,9 +276,11 @@ def addhost(name, addr):
# #
def on_exit(): def on_exit():
if DEBUG > 0: if DEBUG > 0: sys.stderr.write("on_exit\n")
sys.stderr.write("on_exit\n") try:
logf.close() logf.close()
except:
pass
print "exit" print "exit"
@@ -367,11 +367,9 @@ def fromaddr(name, addr, boot, interval, acks):
# #
def readsock(sock): def readsock(sock):
global htab global htab
if DEBUG > 3: if DEBUG > 3: sys.stderr.write("readsock recfrom start")
sys.stderr.write("readsock recfrom start")
data, addr = sock.recvfrom(1024) data, addr = sock.recvfrom(1024)
if DEBUG > 2: if DEBUG > 2: sys.stderr.write("readsock = %s, %s\n" % (data,addr))
sys.stderr.write("readsock = %s, %s\n" % (data,addr))
pairs = string.split(data, ';') pairs = string.split(data, ';')
boot = 0 boot = 0
shutdown = 0 shutdown = 0
@@ -455,20 +453,32 @@ def readsock(sock):
log("%s command initiated" % name) log("%s command initiated" % name)
try: try:
ss=sock.sendto(rmsg, addr) ss=sock.sendto(rmsg, addr)
if DEBUG > 2: if DEBUG > 2: print "msg from %s,%s, sent %s bytes back" % (addr[0], addr[1], ss)
print "msg from %s,%s, sent %s bytes back" % (addr[0], addr[1], ss)
except: except:
pass pass
# #
# #
class HtmlServer(SocketServer.TCPServer):
allow_reuse_address = True
#
#
class HtmlHandler(SocketServer.BaseRequestHandler):
#class HttpServer(BaseHTTPServer.HTTPServer):
class HttpServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
allow_reuse_address = True
def threaded():
pass
#
#
class HttpHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_HEAD(self):
self.send_response(200)
self.send_header("Last-Modified", time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)))
# self.send_header("Accept-Ranges","bytes")
# self.send_header("Connection","close")
self.send_header("Content-Type","text/html; charset = ISO-8859-1")
self.end_headers()
def buildhead(self, title="Heartbeat", refresh=None): def buildhead(self, title="Heartbeat", refresh=None):
res=[] res=[]
@@ -508,41 +518,26 @@ class HtmlHandler(SocketServer.BaseRequestHandler):
res.append('<h1>%s</h1>' % (cause)) res.append('<h1>%s</h1>' % (cause))
res.append('<p>%s</p>' % lcause) res.append('<p>%s</p>' % lcause)
res.append('<hr>') res.append('<hr>')
res.append('<address>hbd (Unix) Server at %s Port %s</address>' % (hbd_host, hbd_port)) res.append('<address>hbd (Unix) Server at %s:%s</address>' % (hbd_host, hbd_port))
res.append('</body></html>') res.append('</body></html>')
return res return res
def handle(self):
global sig, running
headers=[]
headers.append("Date: %s" % time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)))
headers.append("Server: hbd")
headers.append("Last-Modified: %s" % time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime(now)))
headers.append("Accept-Ranges: bytes")
headers.append("Connection: close")
headers.append("Content-Type: text/html; charset = ISO-8859-1")
uri = '/unknown' def do_GET(self):
f = self.request.makefile() global sig
while 1: xsig = 0
try: self.do_HEAD()
line = string.strip(f.readline()) headers=[]
except:
line = '' if DEBUG > 2: sys.stderr.write("handle\n")
if len(line) == 0: uri = self.path
break
r = line.split()
if r[0] == "GET":
uri = r[1]
html = r[2]
upar=string.split(uri,"?") upar=string.split(uri,"?")
if len(upar) == 1: if len(upar) == 1:
uarg=[] uarg=[]
else: else:
uarg=string.split(upar[1],"&") uarg=string.split(upar[1],"&")
if DEBUG > 2: if DEBUG > 2: sys.stderr.write("handle = %s\n" % (uri))
sys.stderr.write("handle = %s\n" % (uri))
code = 200 code = 200
cause = "OK" cause = "OK"
if uri == "/": if uri == "/":
@@ -599,8 +594,7 @@ class HtmlHandler(SocketServer.BaseRequestHandler):
elif upar[0] == "/r": # restart elif upar[0] == "/r": # restart
res=self.buildhead() res=self.buildhead()
res.append("restart request") res.append("restart request")
sig=signal.SIGHUP xsig=signal.SIGHUP
running=False
log("restart request") log("restart request")
else: else:
@@ -609,7 +603,7 @@ class HtmlHandler(SocketServer.BaseRequestHandler):
res=self.builderror(code, cause, "The requested URL was not found on this server.") res=self.builderror(code, cause, "The requested URL was not found on this server.")
tosend = ["HTTP/1.0 %s %s\r" % (code, cause)] tosend = []
for h in headers: for h in headers:
tosend.append("%s\r" % h) tosend.append("%s\r" % h)
tosend.append("\r") tosend.append("\r")
@@ -619,13 +613,19 @@ class HtmlHandler(SocketServer.BaseRequestHandler):
# self.request.send("\r\n") # self.request.send("\r\n")
tosend += res tosend += res
try: self.wfile.write(string.join(tosend, "\n"))
self.request.send(string.join(tosend, "\n"))
except: if xsig:
pass sig = xsig
def setrunning(new):
global running
if DEBUG > 0: sys.stderr.write("running is now = %s\n" % (new))
running = new
def saveandrestart(): def closeup():
setrunning(False)
try: try:
sock.close() sock.close()
except: except:
@@ -634,16 +634,36 @@ def saveandrestart():
sock6.close() sock6.close()
except: except:
pass pass
if DEBUG > 0: sys.stderr.write("asking http server to stop\n")
try:
serv.shutdown()
if DEBUG > 0: sys.stderr.write("http server stopped\n")
except Exception as e:
if DEBUG > 0: sys.stderr.write("http server did NOT stop: %s\n" % str(e))
try: try:
serv.server_close() serv.server_close()
except: except:
pass pass
log("restarting") log("restarting")
try: try:
logf.close() logf.close()
except: except:
pass pass
signal.signal(signal.SIGTERM, 0)
signal.signal(signal.SIGHUP, 0)
def restart():
print "execv %s %s" % (sys.argv[0], [sys.argv[0]]+cmdargs)
os.execv(sys.argv[0], [sys.argv[0]]+cmdargs) os.execv(sys.argv[0], [sys.argv[0]]+cmdargs)
print "should not be here"
def saveandrestart():
closeup()
restart()
def pickleit(): def pickleit():
@@ -686,8 +706,8 @@ for o, a in optlist:
verbose = True verbose = True
cmdargs += [o] cmdargs += [o]
elif o == '-x': elif o == '-x':
DEBUG = True DEBUG += 1
cmdargs += [o]
if helpflag: if helpflag:
print "hbc HeartBeatDaemon" print "hbc HeartBeatDaemon"
@@ -698,7 +718,7 @@ if helpflag:
print " -f run in foreground" print " -f run in foreground"
print " -h this help" print " -h this help"
print " -v verbose" print " -v verbose"
print " -x debug" print " -x increase debug lvl"
print print
print """ config file can contain print """ config file can contain
logfile = /var/log/heartbeat.log logfile = /var/log/heartbeat.log
@@ -731,7 +751,7 @@ try:
if verbose: if verbose:
print "notice: using config file %s" % configfile print "notice: using config file %s" % configfile
except: except:
print "warning: running without conifig file: %s" % configfile print "warning: running without config file: %s" % configfile
f = None f = None
if f: if f:
@@ -814,8 +834,11 @@ sock6.bind(("", hb_port))
ilist.append(sock6) ilist.append(sock6)
serv = HtmlServer((hbd_host, hbd_port), HtmlHandler) serv = HttpServer((hbd_host, hbd_port), HttpHandler)
ilist.append(serv.fileno()) servthread = threading.Thread(target=serv.serve_forever)
servthread.start()
#ilist.append(serv.fileno())
if not forground: if not forground:
pid = os.fork() pid = os.fork()
@@ -840,35 +863,39 @@ sig = 0
signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGTERM, handler)
signal.signal(signal.SIGHUP, handler) signal.signal(signal.SIGHUP, handler)
next = int(now)+15 # 15 seconds time to settle after (re-)start next = int(now)+15 # 15 seconds time to settle after (re-)start
sleep = next - now sleep = 1
while running: firstcheck = int(now) + 15
while running:
sr = None sr = None
if DEBUG > 2: if DEBUG > 2: sys.stderr.write("about to sleep = %s\n" % (sleep))
sys.stderr.write("about to sleep = %s\n" % (sleep))
try: try:
sr = select.select(ilist, [], [], sleep) sr = select.select(ilist, [], [], sleep)
now = time.time() now = time.time()
except KeyboardInterrupt: except KeyboardInterrupt:
sys.exit(0) sys.stderr.write("Keyboard Interrupt!\n")
running = False
closeup()
continue
except select.error, value: except select.error, value:
if value[0] != 4: # interrupted system call if value[0] != 4: # interrupted system call
print select.error, value sys.stderr.write("select err %s %s" % (select.error, value))
#raise os.error, value #raise os.error, value
continue continue
continue continue
except: except Exception as e:
if DEBUG > 2: sys.stderr.write("select exception %s\n" % (str(e)))
sys.exit(1) sys.exit(1)
if DEBUG > 2: if DEBUG > 2: sys.stderr.write("woke from sleep = %s (%s)\n" % (str(sr), str(ilist)))
sys.stderr.write("woke from sleep = %s (%s)\n" % (str(sr), str(ilist)))
for fh in sr[0]: for fh in sr[0]:
if fh in [sock, sock6]: if fh in [sock, sock6]:
readsock(fh) readsock(fh)
elif fh == serv.fileno(): # elif fh == serv.fileno():
serv.handle_request() # serv.handle_request()
else: else:
print("what happend just now") sys.stderr.write("what happend just now?\n")
if DEBUG > 2: sys.stderr.write("done handling, running is %s, sig is %s\n" % (running, sig))
# check hour/day/week # check hour/day/week
for v in xrange(3): for v in xrange(3):
@@ -879,19 +906,21 @@ while running:
for h in hosts.keys(): for h in hosts.keys():
hosts[h].hdwcounts[v] = [hosts[h].doesack, hosts[h].upcount] hosts[h].hdwcounts[v] = [hosts[h].doesack, hosts[h].upcount]
if now >= next: if now >= next and now >= firstcheck:
next = now+1 next = now+1
checkoverdue() checkoverdue()
sleep = next-now sleep = next-now
if sleep < 0: if sleep < 0:
sys.stderr.write("sleep is negaitive! %s next = %s\n" % (sleep, next)) sys.stderr.write("sleep is negative! %s next = %s\n" % (sleep, next))
sleep = 0 sleep = 0
if DEBUG > 2: if DEBUG > 2: sys.stderr.write("sleep = %s next = %s\n" % (sleep, next))
sys.stderr.write("sleep = %s next = %s\n" % (sleep, next))
if sig != 0:
setrunning(False)
if sig == signal.SIGHUP: if sig == signal.SIGHUP:
if DEBUG > 0: if DEBUG > 0: sys.stderr.write("signal 1 saveandrestart\n")
sys.stderr.write("signal 1 saveandrestart\n")
saveandrestart() saveandrestart()