Logo Search packages:      
Sourcecode: nagstamon version File versions  Download package

nagstamonActions.py

#!/usr/bin/python
# encoding: utf-8

import threading
import gobject
import time
import urllib
import webbrowser
import nagstamonObjects
import commands
import re
# if running on windows import winsound
import platform
if platform.system() == "Windows":
    import winsound

# Garbage collection
import gc


def StartRefreshLoop(servers=None, output=None, conf=None):
    """
    the everlasting refresh cycle - starts refresh cycle for every server as thread
    """
    for server in servers.values():
        if str(conf.servers[server.name].enabled) == "True":
            server.thread = RefreshLoopOneServer(server=server, output=output, conf=conf)
            server.thread.start()
            

00031 class RefreshLoopOneServer(threading.Thread):
    """
    one thread for one server per loop
    """
    # kind of a stop please flag, if set to True run() should run no more
    stopped = False
    # Check flag, if set and thread recognizes do a refresh
    doRefresh = False
    
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        # include threading mechanism
        threading.Thread.__init__(self, name=self.server.name)
        self.setDaemon(1)


00048     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
        

    def run(self):
        while self.stopped == False:
            # debug
            if str(self.conf.debug_mode) == "True":
               print self.server.name, ":", "periodically refreshing output - server is already checking:", self.server.isChecking   
                       
            # check if server is already checked
            if self.server.isChecking == False:
                # set server status for status field in popwin
                self.server.status = "Refreshing"
                gobject.idle_add(self.output.popwin.UpdateStatus, self.server)
                # get current status
                server_status = self.server.GetStatus()

                #debug
                if str(self.conf.debug_mode) == "True":
                   print self.server.name, ": server return value :", server_status 
            
                if server_status == "ERROR":
                    # set server status for stauts field in popwin
                    self.server.status = "ERROR - please check settings/network"
                    gobject.idle_add(self.output.popwin.UpdateStatus, self.server)
                    # tell gobject to care about GUI stuff - refresh display status
                    gobject.idle_add(self.output.RefreshDisplayStatus)
                    # change statusbar to the following error message
                    # wait some seconds
                    time.sleep(10)
                    # show error message in statusbar
                    self.output.statusbar.ShowErrorMessage()
                    # do some cleanup
                    gc.collect()
                    # wait some seconds
                    time.sleep(10)
                else:
                    # set server status for status field in popwin
                    self.server.status = "Connected"
                    # tell gobject to care about GUI stuff - refresh display status
                    gobject.idle_add(self.output.RefreshDisplayStatus)
                    # do some cleanup
                    gc.collect()
                    # as soon as configuration is changed the sleep here will last as long as configured - no restart of thread necessary
                    # split time to wait and check if thread should check - s is 6 * 10 seconds - makes 1 minute
                    for s in range(6):
                        # wait for the doRefresh flag to be True, if it is, do a refresh
                        if self.doRefresh == True:
                            if str(self.conf.debug_mode) == "True":
                                print self.server.name, ":", "forcedly refreshing output - server is already checking:", self.server.isChecking         
                            try:
                                # check if server is already checked
                                if self.server.isChecking == False:
                                    # set server status for status field in popwin
                                    self.server.status = "Refreshing"
                                    gobject.idle_add(self.output.popwin.UpdateStatus, self.server)
                                    # get current status of one given server
                                    server_status = self.server.GetStatus()
                                    # set server status for status field in popwin
                                    if server_status == "ERROR":
                                        self.server.status = "ERROR - please check settings/network"
                                    else:
                                        self.server.status = "Connected"
                                    # tell gobject to care about GUI stuff - refresh display status
                                    gobject.idle_add(self.output.RefreshDisplayStatus)
                                    # do some cleanup
                                    gc.collect()
                            except:
                                pass
                            # reset refresh flag
                            self.doRefresh = False

                        try:    
                            # wait refresh interval - better in try-except because sometimes
                            # threads may cry if they have to finish and there is no "time" anymore                         
                            time.sleep(int(self.conf.update_interval)*10) 
                        except:
                            pass
            else:
                # wait refresh interval - better in try-except because sometimes
                # threads may cry if they have to finish and there is no "time" anymore     
                try:
                    # tell gobject to care about GUI stuff - refresh display status
                    # do some cleanup
                    gc.collect()
                    # as soon as configuration is changed the sleep here will last as long as configured - no restart of thread necessary
                    time.sleep(int(self.conf.update_interval)*60) 
                except:
                    pass
                    
        
    def Stop(self):
        # simply sets the stopped flag to True to let the above while stop this thread when checking next
        self.stopped = True
        
        
    def Refresh(self):
        # simply sets the stopped flag to True to let the above while stop this thread when checking next
        self.doRefresh = True

                    
def RefreshAllServers(servers=None, output=None, conf=None):
    """
    one refreshing action, starts threads, one per polled server
    """    
    for server in servers.values():        
        # check if server is already checked
        if server.isChecking == False and str(conf.servers[server.name].enabled) == "True":
            #debug
            if str(conf.debug_mode) == "True":
               print "Checking server:", server.name
    
            server.thread.Refresh()

            # set server status for status field in popwin
            server.status = "Refreshing"
            gobject.idle_add(output.popwin.UpdateStatus, server)
            
    # do some cleanup
    gc.collect()
    

00174 class Recheck(threading.Thread):
    """
    recheck a clicked service/host
    """
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self, name=self.server.name + "-Recheck")
        self.setDaemon(1)
        

    def run(self):
        # decision about host or service - they have different URLs
        if self.service == None:
            # host
            # get start time from Nagios as HTML to use same timezone setting like the locally installed Nagios
            html = self.server.FetchURL(self.server.nagios_cgi_url + "/cmd.cgi?" + urllib.urlencode({"cmd_typ":"96", "host":self.host}), giveback="html")
            start_time = html.split("NAME='start_time' VALUE='")[1].split("'></b></td></tr>")[0]
            # fill and encode CGI data
            cgi_data = urllib.urlencode({"cmd_typ":"96", "cmd_mod":"2", "host":self.host, "start_time":start_time, "force_check":"on", "btnSubmit":"Commit"})
        else:
            # service @ host
            # get start time from Nagios as HTML to use same timezone setting like the locally instaled Nagios
            html = self.server.FetchURL(self.server.nagios_cgi_url + "/cmd.cgi?" + urllib.urlencode({"cmd_typ":"7", "host":self.host, "service":self.service}), giveback="html")
            start_time = html.split("NAME='start_time' VALUE='")[1].split("'></b></td></tr>")[0]
            # fill and encode CGI data
            cgi_data = urllib.urlencode({"cmd_typ":"7", "cmd_mod":"2", "host":self.host, "service":self.service, "start_time":start_time, "force_check":"on", "btnSubmit":"Commit"})
        # execute POST request
        self.server.FetchURL(self.server.nagios_cgi_url + "/cmd.cgi", giveback="nothing", cgi_data=cgi_data)


00205     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
        
        
00212 class Acknowledge(threading.Thread):
    """
    exceute remote cgi command with parameters from acknowledge dialog 
    """
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self)
        self.setDaemon(1)

    def run(self):
        url = self.server.nagios_cgi_url + "/cmd.cgi"
        # decision about host or service - they have different URLs
        # do not care about the doube %s (%s%s) - its ok, "flags" cares about the necessary "&"
        if self.service == "":
            # host
            cgi_data = urllib.urlencode({"cmd_typ":"33", "cmd_mod":"2", "host":self.host, "com_author":self.author, "com_data":self.comment, "btnSubmit":"Commit"})

        else:
            # service @ host
            cgi_data = urllib.urlencode({"cmd_typ":"34", "cmd_mod":"2", "host":self.host, "service":self.service, "com_author":self.author, "com_data":self.comment, "btnSubmit":"Commit"})

        # running remote cgi command        
        self.server.FetchURL(url, giveback="nothing", cgi_data=cgi_data)

        # acknowledge all services on a host
        if self.acknowledge_all_services == True:
            for s in self.all_services:
                # service @ host
                cgi_data = urllib.urlencode({"cmd_typ":"34", "cmd_mod":"2", "host":self.host, "service":s, "com_author":self.author, "com_data":self.comment, "btnSubmit":"Commit"})
                #running remote cgi command        
                self.server.FetchURL(url, giveback="nothing", cgi_data=cgi_data)

        
00246     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
        
    
00253 class Downtime(threading.Thread):
    """
    exceute remote cgi command with parameters from acknowledge dialog 
    """
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self)
        self.setDaemon(1)

    def run(self):
        # decision about host or service - they have different URLs
        if self.service == "":
            # host
            cgi_data = urllib.urlencode({"cmd_typ":"55","cmd_mod":"2","trigger":"0","childoptions":"0","host":self.host,"com_author":self.author,"com_data":self.comment,"fixed":self.fixed,"start_time":self.start_time,"end_time":self.end_time,"hours":self.hours,"minutes":self.minutes,"btnSubmit":"Commit"})
        else:
            # service @ host
           cgi_data = urllib.urlencode({"cmd_typ":"56","cmd_mod":"2","trigger":"0","childoptions":"0","host":self.host,"service":self.service,"com_author":self.author,"com_data":self.comment,"fixed":self.fixed,"start_time":self.start_time,"end_time":self.end_time,"hours":self.hours,"minutes":self.minutes,"btnSubmit":"Commit"})
        url = self.server.nagios_cgi_url + "/cmd.cgi"
        
        # running remote cgi command
        self.server.FetchURL(url, giveback="nothing", cgi_data=cgi_data)
        

00277     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
        

00284 class CheckForNewVersion(threading.Thread):
    """
        Check for new version of nagstamon using connections of configured servers 
    """    
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self)
        self.setDaemon(1)
        
    
    def run(self):
        # try all servers respectively their net connections, one of them should be able to connect
        # to nagstamon.sourceforge.net
        
        # debug
        if str(self.output.conf.debug_mode) == "True":
           print "Checking for new version..."
        
        for s in self.servers.values():
            # if connecton of a server is not yet used do it now
            if s.CheckingForNewVersion == False:
                # set the flag to lock that connection
                s.CheckingForNewVersion = True
                # remove newline
                version = s.FetchURL("http://nagstamon.sourceforge.net/latest_version", giveback="html").split("\n")[0]
                
                # debug
                if str(self.output.conf.debug_mode) == "True":
                   print "Latest version from sourceforge.net:", version
                
                # if we got a result notify user
                if version != "ERROR":
                    if version == self.output.version:
                        version_status = "latest"
                    else:
                        version_status = "out_of_date"
                    # if we got a result reset all servers checkfornewversion flags, 
                    # notify the user and break out of the for loop
                    for s in self.servers.values(): s.CheckingForNewVersion = False
                    # do not tell user that the version is latest when starting up nagstamon
                    if not (self.mode == "startup" and version_status == "latest"):
                        # gobject.idle_add is necessary to start gtk stuff from thread
                        gobject.idle_add(self.output.CheckForNewVersionDialog, version_status, version) 
                    break
                # reset the servers CheckingForNewVersion flag to allow a later check
                s.CheckingForNewVersion = False


00333     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
    

00340 class PlaySound(threading.Thread):
    """
        play notification sound in a threadified way to omit hanging gui
    """
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self)
        self.setDaemon(1)


    def run(self):
        if self.sound == "WARNING":
            if str(self.conf.notification_default_sound) == "True":
                self.Play(self.Resources + "/warning.wav")
            else:
                self.Play(self.conf.notification_custom_sound_warning)
        elif self.sound == "CRITICAL":
            if str(self.conf.notification_default_sound) == "True":
                self.Play(self.Resources + "/critical.wav")
            else:
                self.Play(self.conf.notification_custom_sound_critical)
        elif self.sound == "DOWN":
            if str(self.conf.notification_default_sound) == "True":
                self.Play(self.Resources + "/hostdown.wav")
            else:
                self.Play(self.conf.notification_custom_sound_down)
        elif self.sound =="FILE":
            self.Play(self.file)
    
    
00371     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)
        
    
00378     def Play(self, file):
        """
            depending on platform choose method to play sound
        """
        # debug
        if str(self.conf.debug_mode) == "True":
            print "Playing sound:", file
        try:
            if not platform.system() == "Windows":
                commands.getoutput("play -q %s" % file)
            else:
                winsound.PlaySound(file, winsound.SND_FILENAME)
        except:
            pass
            
                    
00394 class FlashStatusbar(threading.Thread):
    """
        Flash statusbar in a threadified way to omit hanging gui
    """
    def __init__(self, **kwds):
        # add all keywords to object, every mode searchs inside for its favorite arguments/keywords
        for k in kwds: self.__dict__[k] = kwds[k]
        threading.Thread.__init__(self)
        self.setDaemon(1)


    def run(self):
        # in case of notifying in statusbar do some flashing
        try:
            if self.output.Notifying == True:
                # as long as flashing flag is set statusbar flashes until someone takes care
                while self.output.statusbar.Flashing == True:    
                    # check again because in the mean time this flag could have been changed by NotificationOff()
                    gobject.idle_add(self.output.statusbar.Flash)
                    time.sleep(0.5)
            # reset statusbar
            self.output.statusbar.Label.set_markup(self.output.statusbar.statusbar_labeltext)
        except:
            pass


00420     def __del__(self):
        """
        hopefully a __del__() method may make this object better collectable for gc
        """
        del(self)


def Downtime_get_start_end(server, host):
    # get start and end time from Nagios as HTML - the objectified HTML does not contain the form elements :-(
    # this used to happen in GUI.action_downtime_dialog_show but for a more strict separation it better stays here
    html = server.FetchURL(server.nagios_cgi_url + "/cmd.cgi?" + urllib.urlencode({"cmd_typ":"55", "host":host}), giveback="html")
    start_time = html.split("NAME='start_time' VALUE='")[1].split("'></b></td></tr>")[0]
    end_time = html.split("NAME='end_time' VALUE='")[1].split("'></b></td></tr>")[0]
    # give values back as tuple
    return start_time, end_time


def OpenNagios(widget, server, output):
    # open Nagios main page in your favorite web browser when nagios button is clicked
    # first close popwin
    output.popwin.Close()
    # start browser with URL
    webbrowser.open(server.nagios_url)
    # debug
    if str(output.conf.debug_mode) == "True":
       print server.name, ":", "Open Nagios website", server.nagios_url        


def OpenServices(widget, server, output):
    # open Nagios services in your favorite web browser when service button is clicked
    # first close popwin
    output.popwin.Close()
    # start browser with URL
    webbrowser.open(server.nagios_cgi_url + "/status.cgi?host=all&servicestatustypes=28")
    # debug
    if str(output.conf.debug_mode) == "True":
       print server.name, ":", "Open services website", server.nagios_url + "/status.cgi?host=all&servicestatustypes=28"  
 
   
def OpenHosts(widget, server, output):
    # open Nagios hosts in your favorite web browser when hosts button is clicked
    # first close popwin
    output.popwin.Close()
    # start browser with URL
    webbrowser.open(server.nagios_cgi_url + "/status.cgi?hostgroup=all&style=hostdetail&hoststatustypes=12")
    # debug
    if str(output.conf.debug_mode) == "True":
       print server.name, ":", "Open hosts website", server.nagios_url + "/status.cgi?hostgroup=all&style=hostdetail&hoststatustypes=12"      

    
def TreeViewNagios(server, host, service):
    # if the clicked row does not contain a service it mus be a host, 
    # so the nagios query is different 
    if service is None:
        webbrowser.open(server.nagios_cgi_url + "/extinfo.cgi?type=1&host=" + host)
    else:
        webbrowser.open(server.nagios_cgi_url + "/extinfo.cgi?type=2&host=" + host + "&service=" + service)

        
def TreeViewHTTP(host):
    # open Browser with URL of some Host
    webbrowser.open("http://" + host)
        

def CreateServer(server=None, conf=None):
    # create Server from config
    nagiosserver = nagstamonObjects.NagiosServer(conf=conf)
    nagiosserver.name = server.name
    nagiosserver.nagios_url = server.nagios_url
    nagiosserver.nagios_cgi_url = server.nagios_cgi_url
    nagiosserver.username = server.username
    nagiosserver.password = server.password
    nagiosserver.use_proxy = server.use_proxy
    nagiosserver.use_proxy_from_os = server.use_proxy_from_os
    nagiosserver.proxy_address = server.proxy_address
    nagiosserver.proxy_username = server.proxy_username
    nagiosserver.proxy_password = server.proxy_password
    
    # debug
    if str(conf.debug_mode) == "True":
        print "Created Server", server.name

    return nagiosserver


def OpenNagstamonDownload(output=None):
    """
        Opens Nagstamon Download page after being offered by update check
    """
    # first close popwin
    output.popwin.Close()
    # start browser with URL
    webbrowser.open("http://nagstamon.sourceforge.net/download")
       

def HostIsFilteredOutByRE(host, conf=None):
    """
        helper for applying RE filters in nagstamonGUI.RefreshDisplay()
    """
    try:
        if str(conf.re_host_enabled) == "True":
            pattern = re.compile(conf.re_host_pattern)
            result = pattern.findall(host)
            
            if len(result) > 0:
                if str(conf.re_host_reverse) == "True":
                    return False
                else:
                    return True
            else:
                if str(conf.re_host_reverse) == "True":
                    return True
                else:
                    return False
        
        # if RE are disabled return True because host is not filtered      
        return False
    except:
        pass
        
        
def ServiceIsFilteredOutByRE(service, conf=None):
    """
        helper for applying RE filters in nagstamonGUI.RefreshDisplay()
    """
    try:
        if str(conf.re_service_enabled) == "True":
            pattern = re.compile(conf.re_service_pattern)
            result = pattern.findall(service)
            if len(result) > 0:
                if str(conf.re_service_reverse) == "True":
                    return False
                else:
                    return True
            else:
                if str(conf.re_service_reverse) == "True":
                    return True 
                else:
                    return False
        
        # if RE are disabled return True because host is not filtered      
        return False
    except:
        pass

    

Generated by  Doxygen 1.6.0   Back to index