some code...

This commit is contained in:
Johannes Findeisen 2013-05-16 23:03:00 +02:00
commit cac342582b
19 changed files with 788 additions and 0 deletions

1
README Normal file
View file

@ -0,0 +1 @@
test

2
lib/__init__.py Normal file
View file

@ -0,0 +1,2 @@
from config import *
from core import *

0
lib/config/__init__.py Normal file
View file

36
lib/config/config.py Normal file
View file

@ -0,0 +1,36 @@
import json
from services import serviceList
from filters import parseFilterList
from members import parseMemberList
from hosts import parseHostList
from periods import parsePeriodList
from hostgroups import parseHostGroupList
#from layouts import *
class Config:
def __init__(self, configFile):
self.configfile = configFile
f = open(configFile)
self.config = f.read()
f.close()
self.dict = json.loads(self.config)
self.services = serviceList(self.dict['services'])
self.filters = parseFilterList(self.dict['filters'])
self.members = parseMemberList(self.dict['members'], self.filters)
self.periods = parsePeriodList(self.dict['periods'])
self.hosts = parseHostList(self.dict['hosts'], self.services)
self.hostgroups = parseHostGroupList(self.dict['hostgroups'],
self.hosts,
self.members,
self.periods,
self.services)
#self.layouts = LayoutList(self.dict['layouts'], self.hostgroups)

18
lib/config/filters.py Normal file
View file

@ -0,0 +1,18 @@
class Filter:
def __init__(self, name="", command="", priority=0, comment=""):
self.name = name
self.command = command
self.priority = priority
self.comment = comment
def __str__(self):
return "Filter('Name: " + self.name + "', 'Command: " + self.command + "', 'Priority: " + str(
self.priority) + "')"
def clone(self):
return Filter(self.name, self.command, self.priority, self.comment)
def parseFilterList(filters):
return [Filter(name, **values) for name, values in filters.items()]

57
lib/config/hostgroups.py Normal file
View file

@ -0,0 +1,57 @@
class HostGroup:
def __init__(self, name, members="", hosts="", services="", threshold="", parent="", comment=""):
self.name = name
self.interval = 0
self.members = members
self.hosts = hosts
self.services = services
self.threshold = threshold
self.parent = parent
self.comment = comment
def __str__(self):
ret = "HostGroup: " + self.name + " threshold: " + str(self.threshold) + " parent: " + self.parent + "\n"
ret += "members: {\n"
for itm in self.members:
ret += str(itm) + "\n"
ret += "}\n"
ret += "hosts: {\n"
for itm in self.hosts:
ret += str(itm) + "\n"
ret += "}\n"
ret += "services: {\n"
for itm in self.services:
ret += str(itm) + "\n"
ret += "}\n"
return ret
class HostGroupService:
def __init__(self, service, periods):
self.service = service
self.periods = periods
def __str__(self):
return "HostgroupService { " + str(self.service) + ", " + str(self.periods) + "}"
def parseHostGroupList(hostgroups, hosts, members, periods, services):
parsedHostGroups = []
for hgname, hgValues in hostgroups.items():
hostGroup = HostGroup(hgname)
hostGroup.members = filter(lambda m: m.nameid in hgValues['members'], members)
hostGroup.hosts = filter(lambda h: h.name in hgValues['hosts'], hosts)
hostGroup.threshold = hgValues['threshold']
if 'parent' in hgValues:
hostGroup.parent = hgValues['parent']
hostGroup.services = []
for serviceName, servicePeriods in hgValues['services'].items():
service = filter(lambda s: s.name in serviceName, services)
if not service:
print "warning: Service " + serviceName + " is not defined for Hostgroup " + hgname
continue
service = service[0]
periods = filter(lambda p: p.name in servicePeriods, periods)
hostGroup.services.append(HostGroupService(service, periods))
parsedHostGroups.append(hostGroup)
return parsedHostGroups

105
lib/config/hosts.py Normal file
View file

@ -0,0 +1,105 @@
import re
class Host:
def __init__(self, name="", host="", parent="", services=None, comment=""):
self.name = name
self.host = host
self.parent = parent
self.services = services
self.comment = comment
def __str__(self):
ret = "Host('Name: " + self.name + "', 'access: " + self.host + "', "
if self.parent != "":
ret += "'parent: " + self.parent + "', "
ret += "'HostServices: {"
for s in self.services:
ret += str(s) + "\n"
ret += "}"
return ret
class HostService:
def __init__(self, service, warning="", critical=""):
self.service = service
self.warning = warning
self.critical = critical
def setCommand(self, command):
self.service.command = command
def getCommand(self):
return self.service.command
def __str__(self):
ret = str(self.service)
if self.warning:
ret += "warning: " + str(self.warning)
if self.critical:
ret += "critical: " + str(self.critical)
return ret;
def parseHostList(hosts, services):
'''parse the HostList and replace any command as nessesary '''
#precompiled regexPattern which finds replacements in service strings
pattern = re.compile("@(\w+)")
#get a List of Host Objects and leave services unparsed for this moment
parsedHosts = [Host(name, **values) for name, values in hosts.items()]
#predefined dict to cache service replacements by name
serviceReplacements = {}
for host in parsedHosts:
#list to store HostService Objects
hostServices = []
#lets start to parse the Service Dict.
for servicename, serviceParams in host.services.items():
#bool to check if the service is defined.
found = False
#to a real iteration. just pick the right service
for service in services:
if service.name != servicename: continue
#indicate we found a service
found = True
#check to see if we already regexed our service command
if service.name not in serviceReplacements:
serviceReplacements[service.name] = pattern.findall(service.command)
for params in serviceParams:
#copy replacements from service command
replacements = serviceReplacements[service.name][:]
#for every Host.service.parameter we need a new HostService Object
hostService = HostService(service.clone())
#check if the ServiceParameter contain warnings or critical values
if 'warning' in params:
hostService.warning = params['warning']
del params['warning']
if 'critical' in params:
hostService.critical = params['critical']
del params['critical']
#any remainig parm should be a replacement
for parm in params:
if parm not in replacements:
print "warning: undefined parameter: " + parm + " in host " + host.name + " from service " + service.name
continue
#replace our ServiceCommand with the parameter_value (search, replacement, string)
hostService.setCommand(re.sub('@' + parm, params[parm], hostService.getCommand()))
replacements.remove(parm)
#host will not be inside ServiceParameters, so check this also
if 'host' in replacements:
hostService.setCommand(re.sub('@host', host.host, hostService.getCommand()))
replacements.remove('host')
#replacements should be empty now.
#If not we cannot use this command as some values are missing
if replacements:
print "warning: Hostservice " + servicename + " from host " + host.name + " is ignored because of missing replacements: " + str(
replacements)
else:
#anything ok! add to our valid hostServices
hostServices.append(hostService)
#we could't find the service defined in this host. Service ignored!
if not found:
print "warning: Service " + servicename + " not defined in host " + host.name
#replace host.service member by parsed HostService Objects
host.services = hostServices
return parsedHosts

50
lib/config/layouts.py Normal file
View file

@ -0,0 +1,50 @@
from ..core import logger
class Layout:
def __init__(self, myLayout):
self.name = myLayout
self.enabled = False
self.hostgroups = []
def __str__(self):
ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " "
for group in self.hostgroups:
ret += str(group)
return ret
class LayoutList:
def __init__(self, layouts, hostgroups):
self.layouts = []
self.dict = layouts
self.plugins = []
for k, v in layouts.items():
if k in ("plugins", "Plugins"):
self.plugins = v
continue
else:
l = Layout(k)
for k1, v1 in v.items():
if k1 in ("enabled", "Enabled"):
l.enabled = v1
elif k1 in ("hostgroups", "Hostgroups"):
l.hostgroups = []
for group in v1:
h = None
for hostg in hostgroups:
if hostg.name == group:
h = hostg
break
if h is not None:
l.hostgroups.append(h)
else:
logger.logWarningConfig(file="hostgroups", missing=group)
self.layouts.append(l)
def __str__(self):
ret = ""
ret += "Plugins: " + str(self.plugins) + "\n"
for layout in self.layouts:
ret += str(layout) + "\n"
return ret

44
lib/config/members.py Normal file
View file

@ -0,0 +1,44 @@
import re
class Member:
def __init__(self, nameid, name="", phone="", comment="", parent="", filters=None):
self.nameid = nameid
self.name = name
self.phone = phone
self.filters = filters
self.comment = comment
self.parent = parent
def __str__(self):
ret = "Member Id: " + self.nameid + " Name: " + self.name + " Filters: " + str(self.phone)
for f in self.filters:
ret += str(f)
return ret
class MemberFilter:
def __init__(self, filt, Value):
self.filt = filt
self.value = Value
def __str__(self):
return "Filter:" + str(self.filter) + " Value:" + self.value
def parseMemberList(members, filters):
parsedMembers = [Member(nameid, **values) for nameid, values in members.items()]
for member in parsedMembers:
mFilter = []
for filtername, replacement in member.filters.items():
found = False
for filt in filters:
if filt.name != filtername: continue
found = True
memberFilter = filt.clone()
memberFilter.command = re.sub('@member', replacement, filt.command)
mFilter.append(memberFilter)
if not found:
print "warning: filter: " + filtername + " is not defined in member " + member.name
member.filters = mFilter
return parsedMembers

23
lib/config/periods.py Normal file
View file

@ -0,0 +1,23 @@
class Period:
def __init__(self, name="", year="*", month="*", day="*", week="*",
day_of_week=None, hour="*", minute="*", second="0",
comment=None):
self.name = name
self.year = year # 4-digit year number
self.month = month # month number (1-12)
self.day = day # day of the month (1-31)
self.week = week # ISO week number (1-53)
self.day_of_week = day_of_week # number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun)
self.hour = hour # hour (0-23)
self.minute = minute # minute (0-59)
self.second = second # second (0-59)
self.comment = comment
def __str__(self):
ret = "Period(Name: " + self.name + " Year: " + self.year + " Month: " + self.month + ")"
return ret
def parsePeriodList(periods):
return [Period(name, **values) for name, values in periods.items()]

16
lib/config/services.py Normal file
View file

@ -0,0 +1,16 @@
class Service:
def __init__(self, name="", command="", comment="", parser=""):
self.name = name
self.command = command
self.comment = comment
self.parser = parser
def __str__(self):
return "Service('Name: " + self.name + "', 'Command: " + self.command + ", 'Parser: " + self.parser + "')"
def clone(self):
return Service(self.name, self.command, self.comment)
def serviceList(services):
return [Service(name=key, **values) for key, values in services.items()]

0
lib/core/__init__.py Normal file
View file

28
lib/core/command.py Normal file
View file

@ -0,0 +1,28 @@
import subprocess
class Command:
def __init__(self, command):
self.command = command
self.output = ""
self.error = ""
def __str__(self):
return command
def hasProcessed(self):
return self.output != "" and self.error != ""
def doProcess(self):
process = subprocess.Popen([self.command], stdout=subprocess.PIPE)
self.output, self.error = process.communicate()
def getOutput(self):
if not self.hasProcessed():
self.doProcess()
return self.output
def getError(self):
if not self.hasProcessed():
self.doProcess()
return self.error

132
lib/core/daemon.py Normal file
View file

@ -0,0 +1,132 @@
#!/usr/bin/env python
import sys, os, time, atexit
from signal import SIGTERM
class Daemon:
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Start the daemon
"""
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. daemon already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Start the daemon
self.daemonize()
self.run()
def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist. daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def run(self):
"""
You should override this method when you subclass Daemon.
It will be called after the process has been
daemonized by start() or restart().
"""

12
lib/core/job.py Normal file
View file

@ -0,0 +1,12 @@
"""
This is what job_function needs as parameter for each job to succesfully
execute.
"""
class Job:
def __init__(self, command=None, members=None, host=None, service=None):
self.command = command
self.members = members
self.host = host
self.service = service

View file

@ -0,0 +1,16 @@
from ..core import logger
from ..core.daemon import Daemon
class LinspectorDaemon(Daemon):
def run(self):
while True:
try:
a = 2
logger.writeLogToFile(_logfile, "Running!")
print "running!"
except Exception as err:
#logger.writeLogToFile(_logfile, str(err))
print "failed"
sys.exit(1)
time.sleep(1)

40
lib/core/logger.py Normal file
View file

@ -0,0 +1,40 @@
from datetime import datetime
DEBUG = "[debug]"
NOTICE = "[notice]"
WARNING = "[warning]"
def logVerbose(message, verbose=True):
if verbose:
print DEBUG + " " + str(message)
def logNotice(message, verbose=True):
if verbose:
print NOTICE + " " + str(message)
def logWarning(message):
print WARNING + " " + message
def logWarningConfig(file="file", missing="missing"):
logWarning("in " + file + ": The " + missing + " is not defined")
def writeLogToFile(logfile, message):
f = open(logfile, 'a')
f.write("[" + str(datetime.now()) + "] " + message + '\n')
f.close()
class Logger:
def __init__(self, logfile="/dev/null"):
self.logfile = logfile
def logSomething(message, verbose=False):
f = open(self.logfile, 'a')
f.write("[" + str(datetime.now()) + "] " + message + '\n')
f.close()

25
lib/core/logger.py.orig Normal file
View file

@ -0,0 +1,25 @@
from datetime import datetime
DEBUG = "[debug]"
NOTICE = "[notice]"
WARNING = "[warning]"
def logVerbose(message, verbose = False):
if verbose:
print DEBUG + " " + str(message)
def logNotice(message, verbose = False):
if verbose:
print NOTICE + " " + str(message)
def logWarning(message):
print WARNING + " " + message
def logWarningConfig(file = "file", missing = "missing"):
logWarning("in " + file + ": The " + missing + " is not defined")
def writeLogToFile(logfile, message):
f = open(logfile, 'a')
f.write("[" + str(datetime.now()) + "] " + message + '\n')
f.close()

183
linspector Executable file
View file

@ -0,0 +1,183 @@
#!/usr/bin/python -tt
import os, sys, time, getopt, random
from datetime import datetime
from lib.core.daemon import Daemon
from lib.config.config import Config
from lib.core.command import Command
from lib.core import logger
from apscheduler.scheduler import Scheduler
import pprint
NAME = "linspector"
VERSION = "0.1/TETRIS"
_configfile = str(sys.path[0]) + "/linspector.json"
_logfile = str(sys.path[0]) + "/linspector.log"
_pidfile = "/tmp/linspector.pid"
class LinspectorDaemon(Daemon):
def run(self):
"""
parse the joblist here and add each job to cron.
"""
sched = Scheduler()
sched.start()
x = sched.add_cron_job(job_function, second='*/1', args=['1!'])
if x is not None:
logger.writeLogToFile(_logfile, str(x.__dict__))
else:
logger.writeLogToFile(_logfile, "sdfasdfsdf")
sched.add_cron_job(job_function, second='*/2', args=['2!'])
sched.add_cron_job(job_function, second='*/4', args=['4!'])
sched.add_cron_job(job_function, second='*/5', args=['5!'])
sched.add_cron_job(job_function, second='*/8', args=['8!'])
sched.add_cron_job(job_function, second='*/10', args=['10!'])
sched.add_cron_job(job_function, second='*/20', args=['20!'])
sched.add_cron_job(job_function, second='*/40', args=['40!'])
sched.add_cron_job(job_function, second='*', args=['0!'])
while True:
try:
logger.writeLogToFile(_logfile, "Running!")
except Exception as err:
logger.writeLogToFile(_logfile, str(err))
sys.exit(1)
time.sleep(1)
def job_function(mes):
logger.writeLogToFile(_logfile, "Function: job_function says " + str(mes) + ", from cron.")
def usage():
print "usage: linspector [-cdhlprsSvV]"
print "-c, --config=FILE select configfile to use"
print "-d, --daemonize daemonize process"
print "-h, --help this help"
print "-l, --logfile=FILE set logfile to use"
print "-p, --pidfile=FILE set the pidfile to use (default: /tmp/linspector.pid)"
print "-r, --restart restart the daemon"
print "-s, --start start the daemon"
print "-S, --stop stop the daemon"
print "-v, --verbose verbose mode"
print "-V, --version show version information"
def version():
print NAME + " " + VERSION
print "copyright (c) 2011-2013 by Johannes Findeisen and Rafael Timmerberg"
def main():
try:
opts, args = getopt.getopt(sys.argv[1:],
"hl:c:p:vVrsS",
["help", "logfile=",
"config=", "pidfile=",
"verbose", "version",
"restart", "start", "stop"])
except getopt.GetoptError, err:
print str(err)
usage()
sys.exit(2)
verbose = False
restart = False
start = False
stop = False
for o, a in opts:
if o in ("-v", "--verbose"):
verbose = True
elif o in ("-V", "--version"):
version()
sys.exit()
elif o in ("-h", "--help"):
usage()
sys.exit()
elif o in ("-c", "--config"):
configfile = a
global _configfile
_configfile = a
elif o in ("-l", "--logfile"):
logfile = a
global _logfile
_logfile = a
elif o in ("-p", "--pidfile"):
pidfile = a
global _pidfile
_pidfile = a
elif o in ("-r", "--restart"):
restart = True
elif o in ("-s", "--start"):
start = True
elif o in ("-S", "--stop"):
stop = True
if start is True or restart is True:
config = Config(_configfile)
#pprint.pprint(str(config.layouts))
#pprint.pprint(str(config.dict["hostgroups"]))
#pprint.pprint(str(config.filters.))
"""
for service in config.services:
pprint.pprint(str(service))
for filter in config.filters:
pprint.pprint(str(filter))
for member in config.members:
pprint.pprint(str(member))
for period in config.periods:
pprint.pprint(str(period))
for host in config.hosts:
pprint.pprint(str(host))
"""
for hostgroup in config.hostgroups:
pprint.pprint(str(hostgroup))
#for layout in config.layouts.layouts:
# pprint.pprint(str(layout
#logger.writeLogToFile(_logfile, "config.layouts.lyouts: " + str([str(i) for i in config.layouts.layouts]))
#logger.writeLogToFile(_logfile, "config.hostgroups: " + config.hostgroups)
#logger.writeLogToFile(_logfile, "config.hosts: " + str([str(i) for i in config.hosts]))
#logger.writeLogToFile(_logfile, "config.services: " + str([str(i) for i in config.services]))
#logger.writeLogToFile(_logfile, "config.members: " + str([str(i) for i in config.members]))
#logger.writeLogToFile(_logfile, "config.periods: " + str([str(i) for i in config.periods]))
#logger.writeLogToFile(_logfile, "config.filters: " + str([str(i) for i in config.filters]))
#logger.writeLogToFile(_logfile, "X:" + config.periods[0])
"""
linspector = LinspectorDaemon(_pidfile)
if start is True:
logger.writeLogToFile(_logfile, "Starting Linspector...")
logger.writeLogToFile(_logfile, "Path: " + str(sys.path[0]))
logger.writeLogToFile(_logfile, "Configfile: " + _configfile)
logger.writeLogToFile(_logfile, "Logfile: " + _logfile)
logger.writeLogToFile(_logfile, "Pidfile: " + _pidfile)
linspector.start()
elif stop is True:
logger.writeLogToFile(_logfile, "Stopping Linspector...")
logger.writeLogToFile(_logfile, "Pidfile: " + _pidfile)
linspector.stop()
logger.writeLogToFile(_logfile, "Terminated!")
elif restart is True:
logger.writeLogToFile(_logfile, "Restarting Linspector...")
logger.writeLogToFile(_logfile, "Path: " + str(sys.path[0]))
logger.writeLogToFile(_logfile, "Configfile: " + _configfile)
logger.writeLogToFile(_logfile, "Logfile: " + _logfile)
logger.writeLogToFile(_logfile, "Pidfile: " + _pidfile)
linspector.restart()
sys.exit(0)
"""
if __name__ == "__main__":
main()