#!/usr/bin/env python2
"""
    Should be called from cron. Checks each site in tomcatusers.xml and makes sure that the 
    page is viewable. If it gets a 500 error or a the page fails to load in 15 seconds, the tomcat 
    server for that site is restarted.

    If the file ~username/.tomcat.check exists, then the url in that page is checked rather than a 
    made up URL.

    Copyright  Afrihost.com (PTY) Ltd 2003
    Original file by: Ed Pascoe <ed@pascoe.co.za>
    $Id: tomcatmonitor,v 1.3 2004/02/24 11:25:49 elp Exp $
"""
__author__  = "Ed Pascoe <ed@pascoe.co.za>"
__date__    = "$Date: 2004/02/24 11:25:49 $ "
__version__ = "$Revision: 1.3 $"
__credits__ = "Afrihost.com -- The best webhosting. Ever."

import os.path, sys
if __name__=='__main__': sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0])))
import timeoutsocket

timeoutsocket.setDefaultSocketTimeout(15)
import urllib
import httplib
import urlparse
import time

from xml.dom.ext.reader import PyExpat
import xml.dom.ext
import xml.xpath
from xml.dom import EMPTY_NAMESPACE

tomcatconf="/etc/tomcatusers.xml"

#{{{ class siteinfo: Information about the given site
class siteinfo: 
    #{{{ def __init__(self):
    def __init__(self):
        reader = PyExpat.Reader()
        f=open(tomcatconf,"r")
        self.dom = reader.fromStream(f)
        f.close()
        sitelist=[]
        for node in xml.xpath.Evaluate(r"/tomcat-users/site/info", self.dom.documentElement):
               sitelist.append(node.getAttributeNS(EMPTY_NAMESPACE, u'site'))
        self.sitelist=sitelist
    #}}}
    #{{{ def info(self,site):
    def info(self,site):
        """Returns the dom node for the given site"""
        nodes=xml.xpath.Evaluate(r"/tomcat-users/site/info[@site='%s']" % (site) , self.dom.documentElement)
        if not nodes: return None
        node=nodes[0]
        data={}
        data["site"]          = node.getAttributeNS(EMPTY_NAMESPACE, u'site')
        data["port"]          = node.getAttributeNS(EMPTY_NAMESPACE, u'port')
        data["shutdown_port"] = node.getAttributeNS(EMPTY_NAMESPACE, u'shutdown_port')
        data["heap"]          = node.getAttributeNS(EMPTY_NAMESPACE, u'heap')
        data["user"]          = node.getAttributeNS(EMPTY_NAMESPACE, u'user')
        data["password"]      = node.getAttributeNS(EMPTY_NAMESPACE, u'password')
        data["tomcatdir"]     = node.getAttributeNS(EMPTY_NAMESPACE, u'tomcatdir')
        data["logs"] = os.path.join(data["tomcatdir"],"logs")

        return data
    #}}}
#}}}


#{{{ def sitetest(site,info)
def sitetest(site,info):
    sitedata=info.info(site) 
    checkfile=os.path.join(sitedata["tomcatdir"],"../.tomcat.check")
    if not os.path.exists(checkfile): return

    f=open(checkfile,"r")
    url=f.readline().strip()
    data=urlparse.urlparse(url) #scheme://netloc/path;parameters?query#fragment.
    site=data[1]
    data=("","")+data[2:]
    page=urlparse.urlunparse(data)

    restart=0
    try:
        #Do three reloads of the site. Incase it dies after the first reload
        u= httplib.HTTPConnection(site)
        u.request("GET", page)
        r=u.getresponse()
        #---
        u= httplib.HTTPConnection(site)
        u.request("GET", page)
        r=u.getresponse()
        #---
        u= httplib.HTTPConnection(site)
        u.request("GET", page)
        r=u.getresponse()
        if r.status > 499:
            print time.asctime(), "Tomcat is not running on %s or a tomcat error has occured" % (site)
            restart=1
    except timeoutsocket.Timeout:
        print time.asctime(), "Site %s is frozen or hanging" % (site)
        restart=1
    except IOError:
        print time.asctime(), "Site %s is down" % (site)
        restart=1

    if restart:
        sys.stdout.flush()
        cmd="ulimit -s 2048 ; /usr/local/afribin/tomcatctl -c --site=%s restart" % (site)
        print cmd
        sys.stdout.flush()
        os.system(cmd)
#}}}

s=siteinfo()

for site in  s.sitelist:
    try:
        sitetest(site,s)
    except Exception,e :
        print "Big Whoops on %s "  % (site) , e

#    vim600: sw=4 fdm=marker expandtab sm ts=3
