From 5aea78076183acf0cd0422ac965e2fea2f9bdb76 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:10:51 +0200 Subject: [PATCH 001/268] added docs/ --- Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..48741f1 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ + +all: + +clean: + rm -rf docs + rm -rf log + find . -type f -name "*.pyc" -exec rm -f {} \; + +docs: + epydoc --html -o docs ./lib + +docs-pdf: + epydoc --pdf -o docs ./lib + From 4daaf9c9ce1da89e1c9952682194a731952e0047 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:19:13 +0200 Subject: [PATCH 002/268] docs update test From fa67ad381f7478bfe642c5b7734bed994a70c0d0 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:22:57 +0200 Subject: [PATCH 003/268] some clean changes in Makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 48741f1..6f7d059 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,6 @@ - all: clean: - rm -rf docs rm -rf log find . -type f -name "*.pyc" -exec rm -f {} \; @@ -12,3 +10,5 @@ docs: docs-pdf: epydoc --pdf -o docs ./lib +docs-clean: + rm -rf docs From dd11119f5366048fc1a3b0a080dc3bca74aa1159 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:37:40 +0200 Subject: [PATCH 004/268] added file __init__.py to root --- __init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 __init__.py diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..4230117 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from lib import * From 3df6ffb88fe36c29ae1900bc75862a1d87a40a6d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:38:07 +0200 Subject: [PATCH 005/268] some doc related makefiles changes --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6f7d059..02e5508 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ clean: find . -type f -name "*.pyc" -exec rm -f {} \; docs: - epydoc --html -o docs ./lib + epydoc --html -o docs ./ docs-pdf: - epydoc --pdf -o docs ./lib + epydoc --pdf -o docs ./ docs-clean: rm -rf docs From aca6f93e0befcd2eef3b04bf186da45a87eed4fe Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:39:00 +0200 Subject: [PATCH 006/268] some doc structure changes From 1078b1d1e352e5768cc15593383516ccc6ee2060 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:42:48 +0200 Subject: [PATCH 007/268] doc test changes From b8d2a3535af5ba635ec97792fbcdf9d2208169db Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 01:44:28 +0200 Subject: [PATCH 008/268] added job handling --- lib/config/config.py | 2 +- lib/config/periods.py | 90 +++++++++++++++++++++++++++++++++++++++---- lib/core/job.py | 17 ++++++-- linspector | 20 +++++++++- 4 files changed, 116 insertions(+), 13 deletions(-) diff --git a/lib/config/config.py b/lib/config/config.py index bdd0ea2..eec9c6e 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -23,7 +23,7 @@ class Config: self.members = parseMemberList(self.dict['members'], self.filters, log) - self.periods = parsePeriodList(self.dict['periods']) + self.periods = parsePeriodList(self.dict['periods'],log) self.hosts = parseHostList(self.dict['hosts'], self.services, log) diff --git a/lib/config/periods.py b/lib/config/periods.py index 92c2546..7999ec4 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -1,8 +1,44 @@ -class Period: - def __init__(self, name="", year="*", month="*", day="*", week="*", - day_of_week=None, hour="*", minute="*", second="0", date=None, - comment=None): +from apscheduler.scheduler import Scheduler + + +class Period(object): + def __init__(self, name): self.name = name + + def getName(self): + return self.name + + def createJob(self, scheduler, jobInfo, func): + pass + + +class IntervalPeriod(Period): + def __init__(self, name="", weeks=0,days=0, hours=0, minutes=0, seconds=0, start_date=None, + comment=None): + super(IntervalPeriod, self).__init__(name) + + self.days = days # number of days to wait + self.weeks = weeks # number of weeks to wait + self.hours = hours # number of hours to wait + self.minutes = minutes # number of minutes to wait + self.seconds = seconds # number of seconds to wait + self.start_date = start_date # when to first execute + self.comment = comment # comment + + def createJob(self, scheduler, jobInfo, func): + return scheduler.add_interval_job(func, self.weeks, self.hours, self.minutes, self.seconds, self.start_date, jobInfo) + + + def __str__(self): + ret = "IntervalPeriod(Name: " + self.name + ")" + return ret + + +class CronPeriod(Period): + def __init__(self, name="", year="*", month="*", day="*", week="*", + day_of_week="*", hour="*", minute="*", second="0", + comment=None): + super(CronPeriod, self).__init__(name) self.year = year # 4-digit year number self.month = month # month number (1-12) self.day = day # day of the month (1-31) @@ -15,10 +51,50 @@ class Period: self.date = date def __str__(self): - ret = "Period(Name: " + self.name + " Year: " + self.year + " Month: " + self.month + ")" + ret = "CronPeriod(Name: " + self.name + ")" return ret + + def createJob(self, scheduler, jobInfo, func): + return scheduler.add_cron_job(func, self.year, self.month, self.day, self.week, self.day_of_week, self.hour, self.minute, self.second, jobInfo) + + +class DatePeriod(Period): + def __init__(self, name, date, comment=None): + super(DatePeriod, self).__init__(name) + self.date = date + self.comment = comment + + def __str__(self): + ret = "DatePeriod(Name: " + self.name + ","+ str(self.date) + ")" + return ret + + def createJob(self, scheduler, jobInfo, func): + return scheduler.add_date_job(func, self.date, jobInfo) -def parsePeriodList(periods): - return [Period(name, **values) for name, values in periods.items()] + + + +def parsePeriodList(periodlist,log): + periods=[] + for name, values in periodlist.items(): + if "date" in values: + periods.append(DatePeriod(name, **values)) + break + + for i in [ "weeks","days", "hours", "minutes", "seconds", "start_date"]: + if i in values: + periods.append(IntervalPeriod(name, **values)) + break + + for i in ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"]: + if i in values: + periods.append(CronPeriod(name, **values)) + break + + log.w("ignoring Period: " +str(name)) + log.w("reason: could not determine PeriodType: " + str(values)) + + + return periods diff --git a/lib/core/job.py b/lib/core/job.py index 244a4a0..662c533 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -4,9 +4,18 @@ execute. """ -class Job: - def __init__(self, command=None, members=None, host=None, service=None): - self.command = command +class JobInfo: + def __init__(self, hostgroupname, members, hosts, service, threshold, parent=None): self.members = members - self.host = host + self.hosts = hosts self.service = service + self.threshold = threshold + self.parent = parent + self.name = hostgroupname + service.name + + def __str__(self): + return self.name + + + + diff --git a/linspector b/linspector index 8d5799a..707cc4a 100755 --- a/linspector +++ b/linspector @@ -2,8 +2,10 @@ VERSION = "0.1.1/TETRIS" import argparse +from lib.core.job import JobInfo from lib.core.logger import Logger from lib.config.config import Config +from lib.config.periods import Period from apscheduler.scheduler import Scheduler import logging import subprocess as sp @@ -38,6 +40,9 @@ def parseArgs(): return parser.parse_args() +def handleJob(jobInfo): + print str(jobInfo) + def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) @@ -45,11 +50,24 @@ def main(): log.i("parsed arguments") if args.action == "start": + jobs = [] + scheduler = Scheduler() + scheduler.start() + log.i("starting linspector: reading config... (" + args.config + ")") config = Config(args.config, log) log.d("parsed config: " + str(config)) for hg in config.hostgroups: - log.i(str(hg)) + for hostGroupService in hg.services: + job=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) + for period in hostGroupService.periods: + jobs.append(period.createJob(scheduler, jobInfo, handleJob)) + for job in jobs: + log.i(str(job)) + + + + elif args.action == "stop": log.i("stopping linspector is currently unsupported") elif args.action == "restart": From b94809a34d139fdd2df0dfe52df8a5b4d2615a24 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 01:46:32 +0200 Subject: [PATCH 009/268] new docs --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 02e5508..8d023c2 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ clean: find . -type f -name "*.pyc" -exec rm -f {} \; docs: - epydoc --html -o docs ./ + epydoc --html -o docs . docs-pdf: - epydoc --pdf -o docs ./ + epydoc --pdf -o docs . docs-clean: rm -rf docs From 0c995ac24743e4de67a1e55d09514c75b47a1338 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 01:52:41 +0200 Subject: [PATCH 010/268] corrected typo --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 707cc4a..6d48fb1 100755 --- a/linspector +++ b/linspector @@ -59,7 +59,7 @@ def main(): log.d("parsed config: " + str(config)) for hg in config.hostgroups: for hostGroupService in hg.services: - job=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) + jobInfo=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) for period in hostGroupService.periods: jobs.append(period.createJob(scheduler, jobInfo, handleJob)) for job in jobs: From e09ed0ed60210ae43a091c22a9b01f08e2a924df Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 02:16:50 +0200 Subject: [PATCH 011/268] fixed handling of periods, and linspector.json --- lib/config/periods.py | 18 ++++++++++-------- linspector | 1 + linspector.json | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/config/periods.py b/lib/config/periods.py index 7999ec4..d3e93f3 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -26,7 +26,7 @@ class IntervalPeriod(Period): self.comment = comment # comment def createJob(self, scheduler, jobInfo, func): - return scheduler.add_interval_job(func, self.weeks, self.hours, self.minutes, self.seconds, self.start_date, jobInfo) + return scheduler.add_interval_job(func, self.weeks, self.hours, self.minutes, self.seconds, self.start_date, [jobInfo]) def __str__(self): @@ -36,7 +36,7 @@ class IntervalPeriod(Period): class CronPeriod(Period): def __init__(self, name="", year="*", month="*", day="*", week="*", - day_of_week="*", hour="*", minute="*", second="0", + day_of_week="*", hour="*", minute="*", second="0", start_date=None, comment=None): super(CronPeriod, self).__init__(name) self.year = year # 4-digit year number @@ -47,15 +47,16 @@ class CronPeriod(Period): self.hour = hour # hour (0-23) self.minute = minute # minute (0-59) self.second = second # second (0-59) + self.start_date = start_date self.comment = comment - self.date = date + def __str__(self): ret = "CronPeriod(Name: " + self.name + ")" return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_cron_job(func, self.year, self.month, self.day, self.week, self.day_of_week, self.hour, self.minute, self.second, jobInfo) + return scheduler.add_cron_job(func, self.year, self.month, self.day, self.week, self.day_of_week, self.hour, self.minute, self.second,self.start_date, [jobInfo]) class DatePeriod(Period): @@ -69,7 +70,7 @@ class DatePeriod(Period): return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_date_job(func, self.date, jobInfo) + return scheduler.add_date_job(func, self.date, [jobInfo]) @@ -77,20 +78,21 @@ class DatePeriod(Period): def parsePeriodList(periodlist,log): periods=[] + log.i(periodlist) for name, values in periodlist.items(): if "date" in values: periods.append(DatePeriod(name, **values)) - break + continue for i in [ "weeks","days", "hours", "minutes", "seconds", "start_date"]: if i in values: periods.append(IntervalPeriod(name, **values)) - break + continue for i in ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"]: if i in values: periods.append(CronPeriod(name, **values)) - break + continue log.w("ignoring Period: " +str(name)) log.w("reason: could not determine PeriodType: " + str(values)) diff --git a/linspector b/linspector index 6d48fb1..0f9bf2a 100755 --- a/linspector +++ b/linspector @@ -61,6 +61,7 @@ def main(): for hostGroupService in hg.services: jobInfo=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) for period in hostGroupService.periods: + jobs.append(period.createJob(scheduler, jobInfo, handleJob)) for job in jobs: log.i(str(job)) diff --git a/linspector.json b/linspector.json index ec391ee..e3fbfdb 100644 --- a/linspector.json +++ b/linspector.json @@ -147,7 +147,7 @@ "week": "*", "hour": "*", "minute": "5", - "second": "", + "second": "*", "comment": "Cron Job" }, "do_every_x_times" : { From 524b0ba516b4ac1afe68e3f4a77b263f68c209fa Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 02:29:39 +0200 Subject: [PATCH 012/268] added while true loop --- lib/core/job.py | 2 +- linspector | 8 ++++++-- linspector.json | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index 662c533..33af24e 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -11,7 +11,7 @@ class JobInfo: self.service = service self.threshold = threshold self.parent = parent - self.name = hostgroupname + service.name + self.name = hostgroupname + "_" + service.name def __str__(self): return self.name diff --git a/linspector b/linspector index 0f9bf2a..cc65298 100755 --- a/linspector +++ b/linspector @@ -63,8 +63,12 @@ def main(): for period in hostGroupService.periods: jobs.append(period.createJob(scheduler, jobInfo, handleJob)) - for job in jobs: - log.i(str(job)) + + while True: + try: + time.sleep(10) + except: + pass diff --git a/linspector.json b/linspector.json index e3fbfdb..985060f 100644 --- a/linspector.json +++ b/linspector.json @@ -146,7 +146,7 @@ "day": "*", "week": "*", "hour": "*", - "minute": "5", + "minute": "*/1", "second": "*", "comment": "Cron Job" }, From e1025fda6ce9dcc6b42cdf98077e9ad2014e8aa9 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 02:48:35 +0200 Subject: [PATCH 013/268] changed error in parsing of periods --- lib/config/periods.py | 6 +++--- linspector | 16 ++++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/config/periods.py b/lib/config/periods.py index d3e93f3..970001e 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -56,7 +56,7 @@ class CronPeriod(Period): return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_cron_job(func, self.year, self.month, self.day, self.week, self.day_of_week, self.hour, self.minute, self.second,self.start_date, [jobInfo]) + return scheduler.add_cron_job(func, year=self.year, month=self.month, day=self.day, week=self.week, day_of_week=self.day_of_week, hour=self.hour, minute=self.minute, second=self.second,start_date=self.start_date, args=[jobInfo]) class DatePeriod(Period): @@ -87,12 +87,12 @@ def parsePeriodList(periodlist,log): for i in [ "weeks","days", "hours", "minutes", "seconds", "start_date"]: if i in values: periods.append(IntervalPeriod(name, **values)) - continue + break for i in ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"]: if i in values: periods.append(CronPeriod(name, **values)) - continue + break log.w("ignoring Period: " +str(name)) log.w("reason: could not determine PeriodType: " + str(values)) diff --git a/linspector b/linspector index cc65298..780e158 100755 --- a/linspector +++ b/linspector @@ -7,6 +7,7 @@ from lib.core.logger import Logger from lib.config.config import Config from lib.config.periods import Period from apscheduler.scheduler import Scheduler +import time import logging import subprocess as sp @@ -58,17 +59,24 @@ def main(): config = Config(args.config, log) log.d("parsed config: " + str(config)) for hg in config.hostgroups: + for hostGroupService in hg.services: + log.d(hostGroupService) jobInfo=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) for period in hostGroupService.periods: - + log.d(period) jobs.append(period.createJob(scheduler, jobInfo, handleJob)) + for job in jobs: + log.d(str(job)) while True: try: - time.sleep(10) - except: - pass + time.sleep(1) + except error: + print str(error) + + + From b4641b15e1ab046ed257bd91c098d5d3fe03150c Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 02:57:56 +0200 Subject: [PATCH 014/268] fixed cron an interval in json, added log --- linspector | 9 ++++++--- linspector.json | 12 ++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/linspector b/linspector index 780e158..4cb3c0d 100755 --- a/linspector +++ b/linspector @@ -71,9 +71,12 @@ def main(): while True: try: - time.sleep(1) - except error: - print str(error) + time.sleep(10) + for job in jobs: + log.d(str(job)) + + except: + print "error" diff --git a/linspector.json b/linspector.json index 985060f..4fca70c 100644 --- a/linspector.json +++ b/linspector.json @@ -147,15 +147,15 @@ "week": "*", "hour": "*", "minute": "*/1", - "second": "*", + "second": "0", "comment": "Cron Job" }, "do_every_x_times" : { - "days": "*", - "weeks": "*", - "hours": "*", - "minutes": "5", - "seconds": "", + "days": 0, + "weeks": 0, + "hours": 0, + "minutes": 5, + "seconds": 0, "comment": "Interval Job" }, "next_christmas" : { From be1d71257357917a125322431df044b361f704ee Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 27 May 2013 03:13:08 +0200 Subject: [PATCH 015/268] fixed params in periods, added handle Job stub --- lib/config/periods.py | 2 +- lib/core/job.py | 6 ++++++ linspector | 2 ++ linspector.json | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/config/periods.py b/lib/config/periods.py index 970001e..a74c101 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -26,7 +26,7 @@ class IntervalPeriod(Period): self.comment = comment # comment def createJob(self, scheduler, jobInfo, func): - return scheduler.add_interval_job(func, self.weeks, self.hours, self.minutes, self.seconds, self.start_date, [jobInfo]) + return scheduler.add_interval_job(func, weeks=self.weeks, hours=self.hours, minutes=self.minutes, seconds=self.seconds, start_date=self.start_date, args=[jobInfo]) def __str__(self): diff --git a/lib/core/job.py b/lib/core/job.py index 33af24e..1406196 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -16,6 +16,12 @@ class JobInfo: def __str__(self): return self.name + def setLogger(self, log): + self.log = log + + def handleCall(self): + pass + diff --git a/linspector b/linspector index 4cb3c0d..f749292 100755 --- a/linspector +++ b/linspector @@ -42,6 +42,7 @@ def parseArgs(): def handleJob(jobInfo): + jobInfo.handleCall() print str(jobInfo) def main(): @@ -63,6 +64,7 @@ def main(): for hostGroupService in hg.services: log.d(hostGroupService) jobInfo=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) + jobInfo.setLogger(log) for period in hostGroupService.periods: log.d(period) jobs.append(period.createJob(scheduler, jobInfo, handleJob)) diff --git a/linspector.json b/linspector.json index 4fca70c..e0c49e4 100644 --- a/linspector.json +++ b/linspector.json @@ -214,7 +214,7 @@ "services": { "load": ["twentyfourseven"], - "discusage":["twentyfourseven"], + "discusage":["do_every_x_times"], "ping": ["twentyfourseven"] } } From 88d023937f4d92146f0061ce4ae052f03060d9b6 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 03:54:04 +0200 Subject: [PATCH 016/268] many cleanups and new docs --- lib/config/config.py | 2 +- lib/config/filters.py | 2 +- lib/config/hosts.py | 4 ++-- lib/config/members.py | 4 ++-- lib/config/periods.py | 39 +++++++++++++++------------------------ lib/core/command.py | 4 ++-- lib/core/job.py | 6 +----- lib/core/logger.py | 4 +--- linspector | 17 +++++------------ linspector.json | 14 +++++++------- 10 files changed, 37 insertions(+), 59 deletions(-) diff --git a/lib/config/config.py b/lib/config/config.py index eec9c6e..ac72699 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -34,4 +34,4 @@ class Config: self.services, log) - #self.layouts = LayoutList(self.dict['layouts'], self.hostgroups) + #self.layouts = LayoutList(self.dict['layouts'], self.hostgroups) \ No newline at end of file diff --git a/lib/config/filters.py b/lib/config/filters.py index 23cbd00..06fa5a2 100644 --- a/lib/config/filters.py +++ b/lib/config/filters.py @@ -14,4 +14,4 @@ class Filter: def parseFilterList(filters): - return [Filter(name, **values) for name, values in filters.items()] + return [Filter(name, **values) for name, values in filters.items()] \ No newline at end of file diff --git a/lib/config/hosts.py b/lib/config/hosts.py index 8551b6f..8f76aa4 100644 --- a/lib/config/hosts.py +++ b/lib/config/hosts.py @@ -10,9 +10,9 @@ class Host: self.comment = comment def __str__(self): - ret = "Host('Name: " + self.name + "', 'access: " + self.host + "', " + ret = "Host('Name: " + self.name + "', 'Access: " + self.host + "', " if self.parent != "": - ret += "'parent: " + self.parent + "', " + ret += "'Parent: " + self.parent + "', " ret += "'HostServices: {" for s in self.services: ret += str(s) + "\n" diff --git a/lib/config/members.py b/lib/config/members.py index 6f7762c..9526251 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -18,8 +18,8 @@ class Member: class MemberFilter: - def __init__(self, filt, Value): - self.filt = filt + def __init__(self, filter, Value): + self.filter = filter self.value = Value def __str__(self): diff --git a/lib/config/periods.py b/lib/config/periods.py index a74c101..35ac29a 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -1,6 +1,3 @@ -from apscheduler.scheduler import Scheduler - - class Period(object): def __init__(self, name): self.name = name @@ -13,8 +10,7 @@ class Period(object): class IntervalPeriod(Period): - def __init__(self, name="", weeks=0,days=0, hours=0, minutes=0, seconds=0, start_date=None, - comment=None): + def __init__(self, name="", weeks=0, days=0, hours=0, minutes=0, seconds=0, start_date=None, comment=None): super(IntervalPeriod, self).__init__(name) self.days = days # number of days to wait @@ -26,18 +22,17 @@ class IntervalPeriod(Period): self.comment = comment # comment def createJob(self, scheduler, jobInfo, func): - return scheduler.add_interval_job(func, weeks=self.weeks, hours=self.hours, minutes=self.minutes, seconds=self.seconds, start_date=self.start_date, args=[jobInfo]) - - + return scheduler.add_interval_job(func, weeks=self.weeks, hours=self.hours, minutes=self.minutes, + seconds=self.seconds, start_date=self.start_date, args=[jobInfo]) + def __str__(self): ret = "IntervalPeriod(Name: " + self.name + ")" return ret class CronPeriod(Period): - def __init__(self, name="", year="*", month="*", day="*", week="*", - day_of_week="*", hour="*", minute="*", second="0", start_date=None, - comment=None): + def __init__(self, name="", year="*", month="*", day="*", week="*", day_of_week="*", hour="*", minute="*", + second="0", start_date=None, comment=None): super(CronPeriod, self).__init__(name) self.year = year # 4-digit year number self.month = month # month number (1-12) @@ -50,13 +45,14 @@ class CronPeriod(Period): self.start_date = start_date self.comment = comment - def __str__(self): ret = "CronPeriod(Name: " + self.name + ")" return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_cron_job(func, year=self.year, month=self.month, day=self.day, week=self.week, day_of_week=self.day_of_week, hour=self.hour, minute=self.minute, second=self.second,start_date=self.start_date, args=[jobInfo]) + return scheduler.add_cron_job(func, year=self.year, month=self.month, day=self.day, week=self.week, + day_of_week=self.day_of_week, hour=self.hour, minute=self.minute, + second=self.second, start_date=self.start_date, args=[jobInfo]) class DatePeriod(Period): @@ -66,25 +62,22 @@ class DatePeriod(Period): self.comment = comment def __str__(self): - ret = "DatePeriod(Name: " + self.name + ","+ str(self.date) + ")" + ret = "DatePeriod(Name: " + self.name + ", " + str(self.date) + ")" return ret def createJob(self, scheduler, jobInfo, func): return scheduler.add_date_job(func, self.date, [jobInfo]) - - - -def parsePeriodList(periodlist,log): - periods=[] +def parsePeriodList(periodlist, log): + periods = [] log.i(periodlist) for name, values in periodlist.items(): if "date" in values: periods.append(DatePeriod(name, **values)) continue - for i in [ "weeks","days", "hours", "minutes", "seconds", "start_date"]: + for i in ["weeks", "days", "hours", "minutes", "seconds", "start_date"]: if i in values: periods.append(IntervalPeriod(name, **values)) break @@ -94,9 +87,7 @@ def parsePeriodList(periodlist,log): periods.append(CronPeriod(name, **values)) break - log.w("ignoring Period: " +str(name)) + log.w("ignoring Period: " + str(name)) log.w("reason: could not determine PeriodType: " + str(values)) - - - return periods + return periods \ No newline at end of file diff --git a/lib/core/command.py b/lib/core/command.py index a947a83..315af10 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -8,7 +8,7 @@ class Command: self.error = "" def __str__(self): - return command + return self.command def hasProcessed(self): return self.output != "" and self.error != "" @@ -25,4 +25,4 @@ class Command: def getError(self): if not self.hasProcessed(): self.doProcess() - return self.error + return self.error \ No newline at end of file diff --git a/lib/core/job.py b/lib/core/job.py index 1406196..b8c9876 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -20,8 +20,4 @@ class JobInfo: self.log = log def handleCall(self): - pass - - - - + pass \ No newline at end of file diff --git a/lib/core/logger.py b/lib/core/logger.py index 1d0f21a..8b5e398 100644 --- a/lib/core/logger.py +++ b/lib/core/logger.py @@ -56,6 +56,4 @@ class Logger(): self.log.critical(message) def close(self): - logging.shutdown() - - + logging.shutdown() \ No newline at end of file diff --git a/linspector b/linspector index f749292..59621d4 100755 --- a/linspector +++ b/linspector @@ -1,11 +1,10 @@ #!/usr/bin/python2.7 -tt -VERSION = "0.1.1/TETRIS" +VERSION = "0.2/TETRIS" import argparse from lib.core.job import JobInfo from lib.core.logger import Logger from lib.config.config import Config -from lib.config.periods import Period from apscheduler.scheduler import Scheduler import time import logging @@ -45,6 +44,7 @@ def handleJob(jobInfo): jobInfo.handleCall() print str(jobInfo) + def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) @@ -75,17 +75,10 @@ def main(): try: time.sleep(10) for job in jobs: - log.d(str(job)) - + log.d(str(job)) except: print "error" - - - - - - - + elif args.action == "stop": log.i("stopping linspector is currently unsupported") elif args.action == "restart": @@ -99,4 +92,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/linspector.json b/linspector.json index e0c49e4..6e74608 100644 --- a/linspector.json +++ b/linspector.json @@ -148,19 +148,19 @@ "hour": "*", "minute": "*/1", "second": "0", - "comment": "Cron Job" + "comment": "Cron Job / Every minute" }, "do_every_x_times" : { "days": 0, "weeks": 0, "hours": 0, - "minutes": 5, - "seconds": 0, - "comment": "Interval Job" + "minutes": 0, + "seconds": 10, + "comment": "Interval Job / Every 10 seconds" }, "next_christmas" : { "date": "2013-12-24 20:00:00", - "comment": "Date Job" + "comment": "Date Job / Just one day" } }, "hosts": @@ -214,8 +214,8 @@ "services": { "load": ["twentyfourseven"], - "discusage":["do_every_x_times"], - "ping": ["twentyfourseven"] + "discusage":["twentyfourseven"], + "ping": ["do_every_x_times"] } } }, From ef5551b232ab2ad53e43cf210482e6ef03db9698 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 05:14:41 +0200 Subject: [PATCH 017/268] small typo and structure fixes --- linspector | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/linspector b/linspector index 59621d4..fec3c07 100755 --- a/linspector +++ b/linspector @@ -1,14 +1,15 @@ #!/usr/bin/python2.7 -tt -VERSION = "0.2/TETRIS" +__version__ = "0.2/TETRIS" + import argparse +import time +import logging +import subprocess as sp from lib.core.job import JobInfo from lib.core.logger import Logger from lib.config.config import Config from apscheduler.scheduler import Scheduler -import time -import logging -import subprocess as sp def parseArgs(): @@ -19,7 +20,7 @@ def parseArgs(): parser.add_argument("action", choices=["start", "stop", "restart", "attach"], help="defines if linspector should beeing attached, started, stopped or restarted.") - parser.add_argument("--version", action="version", version="%(prog)s " + str(VERSION)) + parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) parser.add_argument("-c", "--config", default="./linspector.json", help="select configfile to use") parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", From fecc9a66e100217bc1fbd2afb762280c5245b4d8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 05:29:51 +0200 Subject: [PATCH 018/268] added very minimal json config for just pinging two hosts. just as example on how easy it could be to monitor the uptime of hosts. --- linspector.minimal.json | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 linspector.minimal.json diff --git a/linspector.minimal.json b/linspector.minimal.json new file mode 100644 index 0000000..d28f799 --- /dev/null +++ b/linspector.minimal.json @@ -0,0 +1,43 @@ +{ + "services": {"ping": {"command": "ping @host"}}, + "filters": + { + "email": + { + "command": "/usr/bin/warn_the_admin_mail @member @+message", + "comment": "Sends an E-Mail to the member.", + "priority": 1 + } + }, + "members": + { + "hanez": + { + "name": "Johannes Findeisen", + "comment": "Just a nerd doing admin stuff...", + "filters": {"email": "you@hanez.org"} + } + }, + "periods": {"twentyfourseven": {"minute": "*/1", "second": "0", "comment": "Cron Job / Every minute"}}, + "hosts": + { + "hanez1": {"host": "www1.hanez.org", "services": {}}, + "hanez2": {"host": "www2.hanez.org", "services": {}} + }, + "hostgroups": + { + "all": + { + "members": ["hanez"], + "hosts": ["hanez1", "hanez2"], + "threshold": 10, + "services": {"ping": ["twentyfourseven"]} + } + }, + "layouts": {"production": {"hostgroups": ["all"], "enabled": true} + }, + "core": { + "max_logfile_size": 1024000, + "max_logfile_count": 4 + } +} \ No newline at end of file From da4c8e036eddd3fdb2ae35b23a8509339cc6c020 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 05:56:14 +0200 Subject: [PATCH 019/268] some new idea in my NOTES --- NOTES.hanez | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NOTES.hanez b/NOTES.hanez index ee07fe0..01f9cc1 100644 --- a/NOTES.hanez +++ b/NOTES.hanez @@ -73,6 +73,9 @@ * threshold muss in die einzelnden services. raus aus der hostgroup. +* We need an escalation threshold! After this amount of fails the problem will + be escaleted. + * Jeder service braucht einen parser um die daten auszuwerten. das heisst, dass wenn ein service angelegt wird auch ein parser für diesen verfügbar sein muss. generische parser sind bestimmt in vielen fällen möglich aber der alltag wird From 4aefac027c31238b9bb8fa84881231aa38515192 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 18:55:48 +0200 Subject: [PATCH 020/268] small change to the while true loop for making linspector interruptable using ctrl-c --- linspector | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/linspector b/linspector index fec3c07..a19dc39 100755 --- a/linspector +++ b/linspector @@ -73,12 +73,10 @@ def main(): log.d(str(job)) while True: - try: - time.sleep(10) - for job in jobs: - log.d(str(job)) - except: - print "error" + time.sleep(10) + for job in jobs: + log.d(str(job)) + elif args.action == "stop": log.i("stopping linspector is currently unsupported") From 5716238b3afe2c95fe61780a894f1c14280441d5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 18:56:39 +0200 Subject: [PATCH 021/268] typo fix --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index a19dc39..7d67de7 100755 --- a/linspector +++ b/linspector @@ -64,7 +64,7 @@ def main(): for hostGroupService in hg.services: log.d(hostGroupService) - jobInfo=JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) + jobInfo = JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) jobInfo.setLogger(log) for period in hostGroupService.periods: log.d(period) From 9b8941d2ce22b083f11dc5a7edf45fd4c906e00b Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 18:57:16 +0200 Subject: [PATCH 022/268] typo fix --- linspector | 1 - 1 file changed, 1 deletion(-) diff --git a/linspector b/linspector index 7d67de7..85edd29 100755 --- a/linspector +++ b/linspector @@ -77,7 +77,6 @@ def main(): for job in jobs: log.d(str(job)) - elif args.action == "stop": log.i("stopping linspector is currently unsupported") elif args.action == "restart": From cc30bec352288db57a63408cbe0409153862f6ec Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 19:30:49 +0200 Subject: [PATCH 023/268] just added some dummy code to execute shell commands --- lib/core/job.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/core/job.py b/lib/core/job.py index b8c9876..a241123 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -3,6 +3,8 @@ This is what job_function needs as parameter for each job to succesfully execute. """ +import subprocess + class JobInfo: def __init__(self, hostgroupname, members, hosts, service, threshold, parent=None): @@ -11,7 +13,7 @@ class JobInfo: self.service = service self.threshold = threshold self.parent = parent - self.name = hostgroupname + "_" + service.name + self.name = hostgroupname + "_" + service.name + " " + self.service.command def __str__(self): return self.name @@ -20,4 +22,7 @@ class JobInfo: self.log = log def handleCall(self): + #p = subprocess.Popen("df -h", stdout=subprocess.PIPE, shell=True) + #(output, err) = p.communicate() + #print output pass \ No newline at end of file From b1ce131246c51198abec885f9deeeae26df6b44c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 20:27:57 +0200 Subject: [PATCH 024/268] typo fixes --- lib/core/job.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index a241123..1d46bc9 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -1,5 +1,5 @@ """ -This is what job_function needs as parameter for each job to succesfully +This is what job_function needs as parameter for each job to successfully execute. """ @@ -13,7 +13,7 @@ class JobInfo: self.service = service self.threshold = threshold self.parent = parent - self.name = hostgroupname + "_" + service.name + " " + self.service.command + self.name = hostgroupname + "_" + service.name + " " + service.command def __str__(self): return self.name From 8481d207729e92bbbb7eb304e7d5e88f195557b0 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 27 May 2013 20:28:36 +0200 Subject: [PATCH 025/268] uups --- lib/core/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/job.py b/lib/core/job.py index 1d46bc9..c09628d 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -13,7 +13,7 @@ class JobInfo: self.service = service self.threshold = threshold self.parent = parent - self.name = hostgroupname + "_" + service.name + " " + service.command + self.name = hostgroupname + "_" + service.name def __str__(self): return self.name From f3c33a3964d24802f3e86766f881ea51838c5f4c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 28 May 2013 02:42:23 +0200 Subject: [PATCH 026/268] added some core config option --- linspector.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linspector.json b/linspector.json index 6e74608..8b59d5b 100644 --- a/linspector.json +++ b/linspector.json @@ -224,6 +224,7 @@ }, "core": { "max_logfile_size": 1024000, - "max_logfile_count": 4 + "max_logfile_count": 4, + "max_worker_threads": 8 } } From e60890268f5141c4af7e9e61399ca7b9b478f3a8 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 01:03:01 +0200 Subject: [PATCH 027/268] added some logic for jobsprocessing, magically somehow not working... --- lib/config/periods.py | 29 +++++++++++++++-------------- lib/core/command.py | 38 +++++++++++++++++++++++++------------- lib/core/job.py | 24 +++++++++++++++++++----- linspector | 7 +++++-- linspector.json | 4 +--- 5 files changed, 65 insertions(+), 37 deletions(-) diff --git a/lib/config/periods.py b/lib/config/periods.py index 35ac29a..76ddd55 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -71,23 +71,24 @@ class DatePeriod(Period): def parsePeriodList(periodlist, log): periods = [] - log.i(periodlist) + #log.d("values of periodslist: " + str(periodlist.items())) for name, values in periodlist.items(): + if "date" in values: periods.append(DatePeriod(name, **values)) continue - for i in ["weeks", "days", "hours", "minutes", "seconds", "start_date"]: - if i in values: - periods.append(IntervalPeriod(name, **values)) - break - - for i in ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"]: - if i in values: - periods.append(CronPeriod(name, **values)) - break - - log.w("ignoring Period: " + str(name)) - log.w("reason: could not determine PeriodType: " + str(values)) + comp = ["weeks", "days", "hours", "minutes", "seconds", "start_date"] + if len([i for i in comp if i in values]) > 0 : + periods.append(IntervalPeriod(name, **values)) + break + + comp = ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"] + if len([i for i in comp if i in values]) > 0 : + periods.append(CronPeriod(name, **values)) + break + else: + log.w("ignoring Period: " + str(name)) + log.w("reason: could not determine PeriodType: " + str(values)) - return periods \ No newline at end of file + return periods diff --git a/lib/core/command.py b/lib/core/command.py index 315af10..74c1b09 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -1,28 +1,40 @@ -import subprocess - +import subprocess as sp +from subprocess import CalledProcessError +from datetime import datetime as dt class Command: def __init__(self, command): self.command = command self.output = "" self.error = "" + self.retcode = 0 + self.commandStart=0 def __str__(self): return self.command - def hasProcessed(self): - return self.output != "" and self.error != "" - - def doProcess(self): - process = subprocess.Popen([self.command], stdout=subprocess.PIPE) + def call(self): + ''' + self.commandStart = dt.now() + "called at: " + process = sp.Popen(stdout=PIPE, *popenargs, **kwargs) self.output, self.error = process.communicate() - + self.retcode = process.poll() + ''' + try: + print self.command + self.output=sp.check_output(self.command.split(),stderr=sp.STDOUT) + + except CalledProcessError: + self.error=CalledProcessError.output + self.retcode = CalledProcessError.returncode + def getOutput(self): - if not self.hasProcessed(): - self.doProcess() return self.output def getError(self): - if not self.hasProcessed(): - self.doProcess() - return self.error \ No newline at end of file + return self.error + + def getReturnCode(self): + return self.retcode + diff --git a/lib/core/job.py b/lib/core/job.py index c09628d..4c5d446 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -3,7 +3,7 @@ This is what job_function needs as parameter for each job to successfully execute. """ -import subprocess +from command import Command class JobInfo: @@ -14,6 +14,7 @@ class JobInfo: self.threshold = threshold self.parent = parent self.name = hostgroupname + "_" + service.name + self.jobs = [] def __str__(self): return self.name @@ -21,8 +22,21 @@ class JobInfo: def setLogger(self, log): self.log = log + def appendJob(self, job): + self.jobs.append(job) + + def getNextExecutionTime(self): + nextExecution = None + for job in self.jobs: + jobExec = job.trigger.get_next_fire_time() + if nextExecution is None or nextExecution > jobExec: + nextExecution = jobExec + return nextExecution + def handleCall(self): - #p = subprocess.Popen("df -h", stdout=subprocess.PIPE, shell=True) - #(output, err) = p.communicate() - #print output - pass \ No newline at end of file + print "calling command " + str(service.command) + cmd = Command(service.command) + self.log.d("executing command: " + str(command)) + cmd.call() + return cmd + diff --git a/linspector b/linspector index 85edd29..44a79dd 100755 --- a/linspector +++ b/linspector @@ -42,8 +42,11 @@ def parseArgs(): def handleJob(jobInfo): - jobInfo.handleCall() + print "handlejobInfo" print str(jobInfo) + print "executing: " + str(jobInfo.service.command) + jobInfo.handleCall() + def main(): @@ -90,4 +93,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/linspector.json b/linspector.json index 8b59d5b..f8525da 100644 --- a/linspector.json +++ b/linspector.json @@ -213,9 +213,7 @@ "threshold": 10, "services": { - "load": ["twentyfourseven"], - "discusage":["twentyfourseven"], - "ping": ["do_every_x_times"] + "ping": ["do_every_x_times"] } } }, From a9270194232ed792a78166c07734052bc86462f5 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 02:22:59 +0200 Subject: [PATCH 028/268] fixed typo bug silently cought by apscheduler, added notes --- NOTES.ruff | 3 +++ lib/config/periods.py | 2 +- lib/core/job.py | 13 ++++++++----- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/NOTES.ruff b/NOTES.ruff index cd466f7..fe89b38 100644 --- a/NOTES.ruff +++ b/NOTES.ruff @@ -1 +1,4 @@ take "~" as expander to make a ./linspector dir + +(using linspector.minimal) +a host which doesn't define a service (seen in linspector.minimal), is at this point useless. It was intended that the host defines allowed services there. The warning that a hostgroup was defined for a host which has not such a service is supressed because host.services has no items to iterate over(hosts.py l64).Also a service like ping isn't defined anywhere... Not shure if this should be considered as config error or parsing error diff --git a/lib/config/periods.py b/lib/config/periods.py index 76ddd55..2ee50bc 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -66,7 +66,7 @@ class DatePeriod(Period): return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_date_job(func, self.date, [jobInfo]) + return scheduler.add_date_job(func, self.date, jobInfo) def parsePeriodList(periodlist, log): diff --git a/lib/core/job.py b/lib/core/job.py index 4c5d446..ae7df06 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -34,9 +34,12 @@ class JobInfo: return nextExecution def handleCall(self): - print "calling command " + str(service.command) - cmd = Command(service.command) - self.log.d("executing command: " + str(command)) - cmd.call() - return cmd + print "about to call command " + str(self.service.command) + #must find real service command stored in hosts... + #but because of error, mentioned in NOTES,ruff, there is no ping i.e. + + #cmd = Command(service.command) + #self.log.d("executing command: " + str(command)) + #cmd.call() + #return cmd From 6abe86d88ad1b5efc8e6206f9511ce56fe3227c4 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 29 May 2013 06:08:18 +0200 Subject: [PATCH 029/268] docs update, just as reference From 656613a3a82f3e9b7e18b898ec2a1cc278af6d35 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 21:11:48 +0200 Subject: [PATCH 030/268] fixes ping bug in json cfg files --- linspector.json | 4 ++++ linspector.minimal.json | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/linspector.json b/linspector.json index f8525da..82ceb0c 100644 --- a/linspector.json +++ b/linspector.json @@ -199,6 +199,10 @@ "htmlcontent": [ { "url": "@host/test.php", "content": "

Server up!

" } + ], + "ping": + [ + {} ] } } diff --git a/linspector.minimal.json b/linspector.minimal.json index d28f799..63e408b 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -18,10 +18,10 @@ "filters": {"email": "you@hanez.org"} } }, - "periods": {"twentyfourseven": {"minute": "*/1", "second": "0", "comment": "Cron Job / Every minute"}}, + "periods": {"every10Secs": {"seconds": "10", "comment": "Interval job; every 10 seconds"}}, "hosts": { - "hanez1": {"host": "www1.hanez.org", "services": {}}, + "hanez1": {"host": "www1.hanez.org", "services": {"ping":[{}]}}, "hanez2": {"host": "www2.hanez.org", "services": {}} }, "hostgroups": @@ -40,4 +40,4 @@ "max_logfile_size": 1024000, "max_logfile_count": 4 } -} \ No newline at end of file +} From d467aa206be46110db29deb9d5abc76ef244266f Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 21:21:09 +0200 Subject: [PATCH 031/268] no commit msg --- linspector.minimal.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 63e408b..1d7cf89 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -29,9 +29,9 @@ "all": { "members": ["hanez"], - "hosts": ["hanez1", "hanez2"], + "hosts": ["hanez1"], "threshold": 10, - "services": {"ping": ["twentyfourseven"]} + "services": {"ping": ["every10Secs"]} } }, "layouts": {"production": {"hostgroups": ["all"], "enabled": true} From 400bfa7d0756592f5558234fe21a1e78a956b18c Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 22:52:54 +0200 Subject: [PATCH 032/268] fixed parsing of services --- .gitignore | 3 ++- lib/config/hostgroups.py | 26 ++++++++++++++------------ lib/config/hosts.py | 12 +++++++++++- lib/core/job.py | 17 +++++++++++++---- linspector | 10 +++------- linspector.minimal.json | 4 ++-- 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/.gitignore b/.gitignore index 4132524..590d78f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ distfiles files local log -plugins \ No newline at end of file +plugins +.metadata diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index ccc522c..b21099f 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -27,31 +27,33 @@ class HostGroup: class HostGroupService: - def __init__(self, service, periods): - self.service = service + def __init__(self, services, periods): + self.services = services self.periods = periods def __str__(self): - return "HostgroupService { " + str(self.service) + ", " + str(self.periods) + "}" + return "HostgroupService { " + str([str(s) for s in self.services]) + ", " + str([p.name for p in self.periods]) + "}" def parseHostGroupList(hostgroups, hosts, members, periods, services, log): 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.members = [m for m in members if m.nameid in hgValues['members']] + hostGroup.hosts = [h for h in hosts if h.name in hgValues['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 len(service) == 0: - log.w("Service " + serviceName + " is not defined for Hostgroup " + hgname) - continue - service = service[0] - hostGroupPeriods = filter(lambda p: p.name in servicePeriods, periods) - hostGroup.services.append(HostGroupService(service, hostGroupPeriods)) + services = [] + for host in hosts: + service = host.getHostServiceByName(serviceName) + if service is not None: + services.append(service) + else: + log.w("could not find HostService(" +str(serviceName) + ") for host " + host.name) + hostGroupPeriods = [p for p in periods if p.name in servicePeriods] + hostGroup.services.append(HostGroupService(services, hostGroupPeriods)) parsedHostGroups.append(hostGroup) return parsedHostGroups diff --git a/lib/config/hosts.py b/lib/config/hosts.py index 8f76aa4..b3bb29a 100644 --- a/lib/config/hosts.py +++ b/lib/config/hosts.py @@ -8,6 +8,12 @@ class Host: self.parent = parent self.services = services self.comment = comment + + def getHostServiceByName(self, serviceName): + for hostService in self.services: + if serviceName == hostService.service.name: + return hostService.service + return None def __str__(self): ret = "Host('Name: " + self.name + "', 'Access: " + self.host + "', " @@ -89,7 +95,11 @@ def parseHostList(hosts, services, log): 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())) + log.d("replacing host in " + hostService.getCommand()) + comm= re.sub('@host', host.host, hostService.getCommand()) + hostService.setCommand(comm) + log.d("new Command: " +comm) + log.d("set in hostService: " + str(hostService)) replacements.remove('host') #replacements should be empty now. #If not we cannot use this command as some values are missing diff --git a/lib/core/job.py b/lib/core/job.py index ae7df06..bbaf58a 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -5,15 +5,21 @@ execute. from command import Command +def generateId(): + i=0 + while True: + yield i + i+=1 class JobInfo: - def __init__(self, hostgroupname, members, hosts, service, threshold, parent=None): + def __init__(self, hostgroupname, members, hosts, hostServices, threshold, parent=None): self.members = members self.hosts = hosts - self.service = service + self.hostServices = hostServices self.threshold = threshold self.parent = parent - self.name = hostgroupname + "_" + service.name + self.name = generateId() + #self.name = hostgroupname + str([str("_" + s.service.name ) for s in hostServices]) self.jobs = [] def __str__(self): @@ -34,7 +40,10 @@ class JobInfo: return nextExecution def handleCall(self): - print "about to call command " + str(self.service.command) + self.log.d("handle call") + self.log.d([str(s) for s in self.hostServices]) + + #must find real service command stored in hosts... #but because of error, mentioned in NOTES,ruff, there is no ping i.e. diff --git a/linspector b/linspector index 44a79dd..66940cb 100755 --- a/linspector +++ b/linspector @@ -11,6 +11,7 @@ from lib.core.logger import Logger from lib.config.config import Config from apscheduler.scheduler import Scheduler +DEFAULT_CONFIG = "./linspector.minimal.json" def parseArgs(): parser = argparse.ArgumentParser( @@ -21,7 +22,7 @@ def parseArgs(): parser.add_argument("action", choices=["start", "stop", "restart", "attach"], help="defines if linspector should beeing attached, started, stopped or restarted.") parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) - parser.add_argument("-c", "--config", default="./linspector.json", + parser.add_argument("-c", "--config", default=DEFAULT_CONFIG, help="select configfile to use") parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", help="set logfile to use") @@ -42,13 +43,8 @@ def parseArgs(): def handleJob(jobInfo): - print "handlejobInfo" - print str(jobInfo) - print "executing: " + str(jobInfo.service.command) jobInfo.handleCall() - - def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) @@ -67,7 +63,7 @@ def main(): for hostGroupService in hg.services: log.d(hostGroupService) - jobInfo = JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.service, hg.threshold, hg.parent) + jobInfo = JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.services, hg.threshold, hg.parent) jobInfo.setLogger(log) for period in hostGroupService.periods: log.d(period) diff --git a/linspector.minimal.json b/linspector.minimal.json index 1d7cf89..157b139 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -18,7 +18,7 @@ "filters": {"email": "you@hanez.org"} } }, - "periods": {"every10Secs": {"seconds": "10", "comment": "Interval job; every 10 seconds"}}, + "periods": {"shortPeriod": {"seconds": 5, "comment": "Interval job; every 10 seconds"}}, "hosts": { "hanez1": {"host": "www1.hanez.org", "services": {"ping":[{}]}}, @@ -31,7 +31,7 @@ "members": ["hanez"], "hosts": ["hanez1"], "threshold": 10, - "services": {"ping": ["every10Secs"]} + "services": {"ping": ["shortPeriod"]} } }, "layouts": {"production": {"hostgroups": ["all"], "enabled": true} From 0f8fa7ea6cc79d25aea6f068cb8608647da2e00b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 23:16:51 +0200 Subject: [PATCH 033/268] fixed returnType of host.getServiceByName --- lib/config/hosts.py | 7 ++++--- lib/core/job.py | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/config/hosts.py b/lib/config/hosts.py index b3bb29a..a4eccdc 100644 --- a/lib/config/hosts.py +++ b/lib/config/hosts.py @@ -12,7 +12,7 @@ class Host: def getHostServiceByName(self, serviceName): for hostService in self.services: if serviceName == hostService.service.name: - return hostService.service + return hostService return None def __str__(self): @@ -39,7 +39,8 @@ class HostService: return self.service.command def __str__(self): - ret = str(self.service) + + ret = "HostService : " + str(self.service) if self.warning: ret += "warning: " + str(self.warning) if self.critical: @@ -103,7 +104,7 @@ def parseHostList(hosts, services, log): replacements.remove('host') #replacements should be empty now. #If not we cannot use this command as some values are missing - if replacements: + if len(replacements) > 0: log.w("Hostservice " + servicename + " from host " + host.name + " is ignored because of missing replacements: " + str( replacements)) else: diff --git a/lib/core/job.py b/lib/core/job.py index bbaf58a..8cf684a 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -41,7 +41,9 @@ class JobInfo: def handleCall(self): self.log.d("handle call") - self.log.d([str(s) for s in self.hostServices]) + self.log.d(self.hostServices) + for hs in self.hostServices: + log.d(str(hs)) #must find real service command stored in hosts... From a1e95212d57676e866fd3a554686097cc3c74da9 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 23:39:16 +0200 Subject: [PATCH 034/268] executing real job, but error handling still won't work --- lib/core/command.py | 22 ++++++++++++++++------ lib/core/job.py | 11 +++++++++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/core/command.py b/lib/core/command.py index 74c1b09..ea91457 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -1,12 +1,14 @@ import subprocess as sp +from subprocess import Popen from subprocess import CalledProcessError from datetime import datetime as dt class Command: - def __init__(self, command): + def __init__(self, command, log): self.command = command - self.output = "" - self.error = "" + self.log = log + self.output = None + self.error = None self.retcode = 0 self.commandStart=0 @@ -22,18 +24,26 @@ class Command: self.retcode = process.poll() ''' try: - print self.command - self.output=sp.check_output(self.command.split(),stderr=sp.STDOUT) - + self.commandStart = dt.now() + self.log.d("calling command " + str(self.command) + " at " + str(self.commandStart)) + self.output=sp.check_output(self.command.split()) + #process = Popen(stdout=PIPE, *popenargs, **kwargs) + #self.output, self.error = process.communicate() + #self.retcode = process.poll() except CalledProcessError: self.error=CalledProcessError.output self.retcode = CalledProcessError.returncode + except Error: + self.log.d("error: " + str(Error)) def getOutput(self): return self.output def getError(self): return self.error + + def getOutputAll(self): + return str(self.output) + str(self.error) + str(self.retcode) def getReturnCode(self): return self.retcode diff --git a/lib/core/job.py b/lib/core/job.py index 8cf684a..3c9d7e6 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -42,8 +42,15 @@ class JobInfo: def handleCall(self): self.log.d("handle call") self.log.d(self.hostServices) - for hs in self.hostServices: - log.d(str(hs)) + try: + + for hs in self.hostServices: + self.log.d(str(hs)) + cmd=Command(hs.service.command, self.log) + cmd.call() + log.d(cmd.getOutputOrError()) + except Error: + self.log.d(Error) #must find real service command stored in hosts... From fb38746eb7e5b8f2f565c2e9ba937516946026a2 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 29 May 2013 23:51:12 +0200 Subject: [PATCH 035/268] switched to Popen, with errors... --- lib/core/command.py | 11 ++++++----- lib/core/job.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/core/command.py b/lib/core/command.py index ea91457..487a54c 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -26,10 +26,11 @@ class Command: try: self.commandStart = dt.now() self.log.d("calling command " + str(self.command) + " at " + str(self.commandStart)) - self.output=sp.check_output(self.command.split()) - #process = Popen(stdout=PIPE, *popenargs, **kwargs) - #self.output, self.error = process.communicate() - #self.retcode = process.poll() + #self.output=sp.check_output(self.command.split()) + process = Popen(stdout=PIPE, *self.command.split()) + self.output, self.error = process.communicate() + self.log.d(str(self.output) + str(self.error)) + self.retcode = process.poll() except CalledProcessError: self.error=CalledProcessError.output self.retcode = CalledProcessError.returncode @@ -42,7 +43,7 @@ class Command: def getError(self): return self.error - def getOutputAll(self): + def getAllOutput(self): return str(self.output) + str(self.error) + str(self.retcode) def getReturnCode(self): diff --git a/lib/core/job.py b/lib/core/job.py index 3c9d7e6..e14ab19 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -48,7 +48,7 @@ class JobInfo: self.log.d(str(hs)) cmd=Command(hs.service.command, self.log) cmd.call() - log.d(cmd.getOutputOrError()) + self.log.d(cmd.getAllOutput()) except Error: self.log.d(Error) From fbdbaf419fb726467e9bae4b0ad5d6a3cc9622de Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 30 May 2013 00:12:34 +0200 Subject: [PATCH 036/268] calling is actually working --- lib/core/command.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/core/command.py b/lib/core/command.py index 487a54c..9bc2e70 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -27,15 +27,15 @@ class Command: self.commandStart = dt.now() self.log.d("calling command " + str(self.command) + " at " + str(self.commandStart)) #self.output=sp.check_output(self.command.split()) - process = Popen(stdout=PIPE, *self.command.split()) + process = Popen(self.command, stdout=sp.PIPE, stderr=sp.PIPE, shell=True) self.output, self.error = process.communicate() - self.log.d(str(self.output) + str(self.error)) + self.log.d(str(self.output)) + self.log.d(str(self.error)) self.retcode = process.poll() except CalledProcessError: self.error=CalledProcessError.output self.retcode = CalledProcessError.returncode - except Error: - self.log.d("error: " + str(Error)) + def getOutput(self): return self.output From af8071a5ed3cabbb87cc046e282563bbd8e5c578 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 00:30:19 +0200 Subject: [PATCH 037/268] working minimal json with two existing hosts --- linspector.minimal.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 157b139..9cbf26d 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -1,5 +1,5 @@ { - "services": {"ping": {"command": "ping @host"}}, + "services": {"ping": {"command": "ping -c 1 @host"}}, "filters": { "email": @@ -21,15 +21,15 @@ "periods": {"shortPeriod": {"seconds": 5, "comment": "Interval job; every 10 seconds"}}, "hosts": { - "hanez1": {"host": "www1.hanez.org", "services": {"ping":[{}]}}, - "hanez2": {"host": "www2.hanez.org", "services": {}} + "a.systemchaos.org": {"host": "a.systemchaos.org", "services": {"ping":[{}]}}, + "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}} }, "hostgroups": { "all": { "members": ["hanez"], - "hosts": ["hanez1"], + "hosts": ["a.systemchaos.org", "b.systemchaos.org"], "threshold": 10, "services": {"ping": ["shortPeriod"]} } From 3276b3837cfe4ef30dcc36aa464ce5f09196743b Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 00:36:22 +0200 Subject: [PATCH 038/268] added google.de to minimal json --- linspector.minimal.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 9cbf26d..91a6b38 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -22,14 +22,15 @@ "hosts": { "a.systemchaos.org": {"host": "a.systemchaos.org", "services": {"ping":[{}]}}, - "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}} + "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}}, + "google.de": {"host": "google.de", "services": {"ping":[{}]}} }, "hostgroups": { "all": { "members": ["hanez"], - "hosts": ["a.systemchaos.org", "b.systemchaos.org"], + "hosts": ["a.systemchaos.org", "b.systemchaos.org", "google.de"], "threshold": 10, "services": {"ping": ["shortPeriod"]} } From e7d6e3bbbd9d626bd98071eb42cf0412a12d79a7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 00:42:13 +0200 Subject: [PATCH 039/268] next version... 0.3 --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 66940cb..cbb41c4 100755 --- a/linspector +++ b/linspector @@ -1,6 +1,6 @@ #!/usr/bin/python2.7 -tt -__version__ = "0.2/TETRIS" +__version__ = "0.3/TETRIS" import argparse import time From d7eb2aed7fad6dd1aa63b3bc3fa68a589ec7f3bf Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 00:45:46 +0200 Subject: [PATCH 040/268] new docs for version 0.3 From 525c65edea57c2598cbb2ecad4f60b7fff5e74f0 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 30 May 2013 01:02:24 +0200 Subject: [PATCH 041/268] changed logging --- lib/core/command.py | 2 +- lib/core/job.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/core/command.py b/lib/core/command.py index 9bc2e70..6a91ee7 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -25,7 +25,7 @@ class Command: ''' try: self.commandStart = dt.now() - self.log.d("calling command " + str(self.command) + " at " + str(self.commandStart)) + self.log.i("calling command " + str(self.command) + " at " + str(self.commandStart)) #self.output=sp.check_output(self.command.split()) process = Popen(self.command, stdout=sp.PIPE, stderr=sp.PIPE, shell=True) self.output, self.error = process.communicate() diff --git a/lib/core/job.py b/lib/core/job.py index e14ab19..837b22b 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -23,7 +23,7 @@ class JobInfo: self.jobs = [] def __str__(self): - return self.name + return "JobInfo " + str(self.name) def setLogger(self, log): self.log = log @@ -49,8 +49,8 @@ class JobInfo: cmd=Command(hs.service.command, self.log) cmd.call() self.log.d(cmd.getAllOutput()) - except Error: - self.log.d(Error) + except Exception: + self.log.d(Exception) #must find real service command stored in hosts... From ee1d6c4104d5674875e5483d872b159c36b41d68 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 02:19:14 +0200 Subject: [PATCH 042/268] added lib/parser + dummy --- lib/__init__.py | 1 + lib/parser/__init__.py | 0 lib/parser/parser.py | 0 3 files changed, 1 insertion(+) create mode 100644 lib/parser/__init__.py create mode 100644 lib/parser/parser.py diff --git a/lib/__init__.py b/lib/__init__.py index 1e5d6a9..e82f103 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,2 +1,3 @@ from config import * from core import * +from parser import * \ No newline at end of file diff --git a/lib/parser/__init__.py b/lib/parser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/parser/parser.py b/lib/parser/parser.py new file mode 100644 index 0000000..e69de29 From dc0c54bc5b6ef1f3e964104f8284369b3afd3b61 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 02:25:20 +0200 Subject: [PATCH 043/268] added some parser foo... just some idea. --- linspector.minimal.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 91a6b38..c3f1883 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -21,7 +21,7 @@ "periods": {"shortPeriod": {"seconds": 5, "comment": "Interval job; every 10 seconds"}}, "hosts": { - "a.systemchaos.org": {"host": "a.systemchaos.org", "services": {"ping":[{}]}}, + "a.systemchaos.org": {"host": "a.systemchaos.org", "services": {"ping":[{ "parser": { "name": "df", "line": 2, "col": 5 }}]}}, "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}}, "google.de": {"host": "google.de", "services": {"ping":[{}]}} }, From 88b0c3dd7ab320589e0070afad300f397359b880 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 04:20:35 +0200 Subject: [PATCH 044/268] housekeeping and cleanups... --- lib/config/hostgroups.py | 2 +- lib/config/hosts.py | 6 +++--- lib/core/command.py | 24 +++++++++++------------- lib/core/job.py | 22 +++++++--------------- linspector | 2 +- 5 files changed, 23 insertions(+), 33 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index b21099f..87d03cb 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -52,7 +52,7 @@ def parseHostGroupList(hostgroups, hosts, members, periods, services, log): if service is not None: services.append(service) else: - log.w("could not find HostService(" +str(serviceName) + ") for host " + host.name) + log.w("could not find HostService(" + str(serviceName) + ") for host " + host.name) hostGroupPeriods = [p for p in periods if p.name in servicePeriods] hostGroup.services.append(HostGroupService(services, hostGroupPeriods)) parsedHostGroups.append(hostGroup) diff --git a/lib/config/hosts.py b/lib/config/hosts.py index a4eccdc..afffc90 100644 --- a/lib/config/hosts.py +++ b/lib/config/hosts.py @@ -45,12 +45,12 @@ class HostService: ret += "warning: " + str(self.warning) if self.critical: ret += "critical: " + str(self.critical) - return ret; + return ret def parseHostList(hosts, services, log): """ - parse the HostList and replace any command as nessesary + parse the HostList and replace any command as necessary """ #precompiled regexPattern which finds replacements in service strings pattern = re.compile("@(\w+)") @@ -97,7 +97,7 @@ def parseHostList(hosts, services, log): #host will not be inside ServiceParameters, so check this also if 'host' in replacements: log.d("replacing host in " + hostService.getCommand()) - comm= re.sub('@host', host.host, hostService.getCommand()) + comm = re.sub('@host', host.host, hostService.getCommand()) hostService.setCommand(comm) log.d("new Command: " +comm) log.d("set in hostService: " + str(hostService)) diff --git a/lib/core/command.py b/lib/core/command.py index 6a91ee7..3bd0d88 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -10,19 +10,19 @@ class Command: self.output = None self.error = None self.retcode = 0 - self.commandStart=0 + self.commandStart = 0 def __str__(self): return self.command def call(self): - ''' - self.commandStart = dt.now() - "called at: " - process = sp.Popen(stdout=PIPE, *popenargs, **kwargs) - self.output, self.error = process.communicate() - self.retcode = process.poll() - ''' + + # self.commandStart = dt.now() + # "called at: " + # process = sp.Popen(stdout=PIPE, *popenargs, **kwargs) + # self.output, self.error = process.communicate() + # self.retcode = process.poll() + try: self.commandStart = dt.now() self.log.i("calling command " + str(self.command) + " at " + str(self.commandStart)) @@ -33,10 +33,9 @@ class Command: self.log.d(str(self.error)) self.retcode = process.poll() except CalledProcessError: - self.error=CalledProcessError.output + self.error = CalledProcessError.output self.retcode = CalledProcessError.returncode - - + def getOutput(self): return self.output @@ -47,5 +46,4 @@ class Command: return str(self.output) + str(self.error) + str(self.retcode) def getReturnCode(self): - return self.retcode - + return self.retcode \ No newline at end of file diff --git a/lib/core/job.py b/lib/core/job.py index 837b22b..8f61e52 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -5,11 +5,13 @@ execute. from command import Command + def generateId(): - i=0 + i = 0 while True: - yield i - i+=1 + yield i + i += 1 + class JobInfo: def __init__(self, hostgroupname, members, hosts, hostServices, threshold, parent=None): @@ -46,18 +48,8 @@ class JobInfo: for hs in self.hostServices: self.log.d(str(hs)) - cmd=Command(hs.service.command, self.log) + cmd = Command(hs.service.command, self.log) cmd.call() self.log.d(cmd.getAllOutput()) except Exception: - self.log.d(Exception) - - - #must find real service command stored in hosts... - #but because of error, mentioned in NOTES,ruff, there is no ping i.e. - - #cmd = Command(service.command) - #self.log.d("executing command: " + str(command)) - #cmd.call() - #return cmd - + self.log.d(Exception) \ No newline at end of file diff --git a/linspector b/linspector index cbb41c4..276eaec 100755 --- a/linspector +++ b/linspector @@ -89,4 +89,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file From 658c37206f78d4865c70b2f5d7b17b2252f9b064 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 04:45:30 +0200 Subject: [PATCH 045/268] added lib/service/ and some dummy files. need to talk about that but i think we should implement the services in pure python --- lib/__init__.py | 3 ++- lib/service/__init__.py | 0 lib/service/htmlcontent.py | 8 ++++++++ lib/service/ping.py | 5 +++++ lib/service/snmpget.py | 5 +++++ lib/service/ssh.py | 5 +++++ 6 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 lib/service/__init__.py create mode 100644 lib/service/htmlcontent.py create mode 100644 lib/service/ping.py create mode 100644 lib/service/snmpget.py create mode 100644 lib/service/ssh.py diff --git a/lib/__init__.py b/lib/__init__.py index e82f103..c79d660 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,3 +1,4 @@ from config import * from core import * -from parser import * \ No newline at end of file +from parser import * +from service import * \ No newline at end of file diff --git a/lib/service/__init__.py b/lib/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/service/htmlcontent.py b/lib/service/htmlcontent.py new file mode 100644 index 0000000..2b3ce39 --- /dev/null +++ b/lib/service/htmlcontent.py @@ -0,0 +1,8 @@ +""" +The htmlcontent service in pure Python. STUPID NAME!!! +""" + +# http://pycurl.sourceforge.net/ --- seems old... +# http://www.angryobjects.com/2011/10/15/http-with-python-pycurl-by-example/ +# +# maybe better: http://docs.python.org/2/library/urllib.html \ No newline at end of file diff --git a/lib/service/ping.py b/lib/service/ping.py new file mode 100644 index 0000000..7cc0b51 --- /dev/null +++ b/lib/service/ping.py @@ -0,0 +1,5 @@ +""" +The ping service in pure Python. +""" + +# http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ \ No newline at end of file diff --git a/lib/service/snmpget.py b/lib/service/snmpget.py new file mode 100644 index 0000000..c36c477 --- /dev/null +++ b/lib/service/snmpget.py @@ -0,0 +1,5 @@ +""" +The snmpget service in pure Python. +""" + +# http://pysnmp.sourceforge.net/ \ No newline at end of file diff --git a/lib/service/ssh.py b/lib/service/ssh.py new file mode 100644 index 0000000..123c460 --- /dev/null +++ b/lib/service/ssh.py @@ -0,0 +1,5 @@ +""" +The ssh service in pure Python. +""" + +# http://www.lag.net/paramiko/ \ No newline at end of file From 6b54c149d134239be57b2c858dc43e74212b626a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 04:53:10 +0200 Subject: [PATCH 046/268] added tcpconnect service. this code could be useful for htmlcontent too. --- lib/service/htmlcontent.py | 4 +++- lib/service/tcpconnect.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lib/service/tcpconnect.py diff --git a/lib/service/htmlcontent.py b/lib/service/htmlcontent.py index 2b3ce39..6d9580c 100644 --- a/lib/service/htmlcontent.py +++ b/lib/service/htmlcontent.py @@ -5,4 +5,6 @@ The htmlcontent service in pure Python. STUPID NAME!!! # http://pycurl.sourceforge.net/ --- seems old... # http://www.angryobjects.com/2011/10/15/http-with-python-pycurl-by-example/ # -# maybe better: http://docs.python.org/2/library/urllib.html \ No newline at end of file +# maybe better: http://docs.python.org/2/library/urllib.html +# +# or look at tcpconnect.py! could be useful to. \ No newline at end of file diff --git a/lib/service/tcpconnect.py b/lib/service/tcpconnect.py new file mode 100644 index 0000000..ba097b2 --- /dev/null +++ b/lib/service/tcpconnect.py @@ -0,0 +1,35 @@ +""" +The tcpconnect service in pure Python. +""" + +import socket +import sys + +HOST = 'linspector.org' +GET = '/index.html' +PORT = 80 + +try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(1) + +try: + sock.connect((HOST, PORT)) +except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(2) + +sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST)) + +data = sock.recv(1024) +string = "" +while len(data): + string = string + data + data = sock.recv(1024) +sock.close() + +print string + +sys.exit(0) \ No newline at end of file From e0b3c6b3691da3e3839ae750f2ec038d40783722 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 04:56:29 +0200 Subject: [PATCH 047/268] just deleted a line so doc generation works --- lib/service/tcpconnect.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/service/tcpconnect.py b/lib/service/tcpconnect.py index ba097b2..18fe5e7 100644 --- a/lib/service/tcpconnect.py +++ b/lib/service/tcpconnect.py @@ -31,5 +31,3 @@ while len(data): sock.close() print string - -sys.exit(0) \ No newline at end of file From 149fc874f5a3627890ad7c04888d5e9fa54ad3bc Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 04:58:21 +0200 Subject: [PATCH 048/268] docs update From 3fb3fcc0eb75af2311cb2782f66ac383ff3c4e0d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 07:58:51 +0200 Subject: [PATCH 049/268] just added some new ideas to minimal json --- linspector.minimal.json | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index c3f1883..4e29167 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -1,5 +1,6 @@ { - "services": {"ping": {"command": "ping -c 1 @host"}}, + "services": {"ping": {"command": "ping -c 1 @host"}, + "tcpconnect": {"command": "tcpconnect @host @port"}}, "filters": { "email": @@ -21,9 +22,24 @@ "periods": {"shortPeriod": {"seconds": 5, "comment": "Interval job; every 10 seconds"}}, "hosts": { - "a.systemchaos.org": {"host": "a.systemchaos.org", "services": {"ping":[{ "parser": { "name": "df", "line": 2, "col": 5 }}]}}, + "a.systemchaos.org": {"host": "a.systemchaos.org", + "services": { + "ping":[{ "args": + { "device": "/dev/sda1" }, + "fails": { "warning": "80%", "critical": "90%" }, + "parser": { "name": "ping", "line": 2, "col": 5 }}] + } + }, "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}}, - "google.de": {"host": "google.de", "services": {"ping":[{}]}} + "google.de": {"host": "google.de", "services": {"ping":[{}]}}, + "foobar.systemchaos.org": {"host": "foobar.systemchaos.org", + "services": { + "tcpconnect":[{ "args": + { "port": 80 }, + "fails": { }, + "parser": { "name": "none" }}] + } + } }, "hostgroups": { From e86447e5db9b651f337c666a5ecf4a69e217cd29 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 08:48:24 +0200 Subject: [PATCH 050/268] cleanup one line --- linspector | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linspector b/linspector index 276eaec..58ed28a 100755 --- a/linspector +++ b/linspector @@ -44,7 +44,8 @@ def parseArgs(): def handleJob(jobInfo): jobInfo.handleCall() - + + def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) From cc355b58d24c9e5a9145b341cdcd3b6f5d322654 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 08:50:26 +0200 Subject: [PATCH 051/268] added lib/filters for pure python filters --- lib/filters/__init__.py | 0 lib/filters/email.py | 3 +++ 2 files changed, 3 insertions(+) create mode 100644 lib/filters/__init__.py create mode 100644 lib/filters/email.py diff --git a/lib/filters/__init__.py b/lib/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/filters/email.py b/lib/filters/email.py new file mode 100644 index 0000000..a625f1a --- /dev/null +++ b/lib/filters/email.py @@ -0,0 +1,3 @@ +""" +The email filter in pure Python. +""" \ No newline at end of file From 6594f26076bc31ad8849ceb8563caca39c0e3188 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 08:50:54 +0200 Subject: [PATCH 052/268] added lib/filters for pure python filters ... for got this file --- lib/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/__init__.py b/lib/__init__.py index c79d660..c14c0bd 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,4 +1,5 @@ from config import * from core import * +from filters import * from parser import * from service import * \ No newline at end of file From 24b3fcee6b64804c49573f429a4a9ce3933bc299 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 09:05:30 +0200 Subject: [PATCH 053/268] added some examples on what we need to configure... --- linspector.minimal.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 4e29167..fbca247 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -5,7 +5,7 @@ { "email": { - "command": "/usr/bin/warn_the_admin_mail @member @+message", + "command": "email @member @+message", "comment": "Sends an E-Mail to the member.", "priority": 1 } @@ -37,8 +37,28 @@ "tcpconnect":[{ "args": { "port": 80 }, "fails": { }, + "threshold": 2, "parser": { "name": "none" }}] } + }, + "snmp.systemchaos.org": {"host": "snmp.systemchaos.org", + "services": { + "snmpget":[{ "args": + { "port": 5555, "oid": "1.3.6.1.4.1.2681.1.2.102." }, + "fails": { "warning": "8", "critical": "16" }, + "parser": { "name": "snmpget" }, + "comment": "Value X from Y"}] + } + }, + "web.systemchaos.org": {"host": "web.systemchaos.org", + "services": { + "htmlcontent":[{ "args": + { "port": 80, "string": "

I am up!

" }, + "fails": { }, + "threshold": 2, + "parser": { "name": "none" }, + "comment": "Just a string grep"}] + } } }, "hostgroups": From c214ffe57d70a1f6906ede2fa0e32c5a3c1ef1cb Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 09:22:39 +0200 Subject: [PATCH 054/268] some fixes and adds --- linspector.minimal.json | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index fbca247..592387c 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -24,40 +24,36 @@ { "a.systemchaos.org": {"host": "a.systemchaos.org", "services": { - "ping":[{ "args": - { "device": "/dev/sda1" }, - "fails": { "warning": "80%", "critical": "90%" }, - "parser": { "name": "ping", "line": 2, "col": 5 }}] + "ping":[{ "args": { "device": "/dev/sda1" }, + "fails": { "warning": "100ms", "critical": "150ms" }, + "parser": { "name": "ping", "line": 2, "col": 5 }}] } }, "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}}, "google.de": {"host": "google.de", "services": {"ping":[{}]}}, "foobar.systemchaos.org": {"host": "foobar.systemchaos.org", "services": { - "tcpconnect":[{ "args": - { "port": 80 }, - "fails": { }, - "threshold": 2, - "parser": { "name": "none" }}] + "tcpconnect":[{ "args": { "port": 80 }, + "fails": { }, + "threshold": 2, + "parser": { "name": "none" }}] } }, "snmp.systemchaos.org": {"host": "snmp.systemchaos.org", "services": { - "snmpget":[{ "args": - { "port": 5555, "oid": "1.3.6.1.4.1.2681.1.2.102." }, - "fails": { "warning": "8", "critical": "16" }, - "parser": { "name": "snmpget" }, - "comment": "Value X from Y"}] + "snmpget":[{ "args": { "port": 5555, "oid": "1.3.6.1.4.1.2681.1.2.102." }, + "fails": { "warning": "8", "critical": "16" }, + "parser": { "name": "snmpget" }, + "comment": "Value X from Y"}] } }, "web.systemchaos.org": {"host": "web.systemchaos.org", "services": { - "htmlcontent":[{ "args": - { "port": 80, "string": "

I am up!

" }, - "fails": { }, - "threshold": 2, - "parser": { "name": "none" }, - "comment": "Just a string grep"}] + "htmlcontent":[{ "args": { "port": 80, "string": "

I am up!

" }, + "fails": { }, + "threshold": 2, + "parser": { "name": "none" }, + "comment": "Just a string grep"}] } } }, From 80b3c0bcc08f3d2d392cec05d0cb407d5c1c8b77 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 30 May 2013 23:07:34 +0200 Subject: [PATCH 055/268] added shell service --- lib/service/shell.py | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 lib/service/shell.py diff --git a/lib/service/shell.py b/lib/service/shell.py new file mode 100644 index 0000000..234b714 --- /dev/null +++ b/lib/service/shell.py @@ -0,0 +1,4 @@ +""" +The shell service. This is for executing services as shell commands and don't use a builtin function. This is useful to +be free to do what you want. +""" \ No newline at end of file From f6df05665a9605a1d87007977d5abdd3f6f3d28a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 31 May 2013 05:13:35 +0200 Subject: [PATCH 056/268] config changes --- linspector.minimal.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector.minimal.json b/linspector.minimal.json index 592387c..878a619 100644 --- a/linspector.minimal.json +++ b/linspector.minimal.json @@ -49,7 +49,7 @@ }, "web.systemchaos.org": {"host": "web.systemchaos.org", "services": { - "htmlcontent":[{ "args": { "port": 80, "string": "

I am up!

" }, + "htmlcontent":[{ "args": { "port": 80, "path": "/status.cgi", "string": "

I am up!

" }, "fails": { }, "threshold": 2, "parser": { "name": "none" }, From 100840e91c49024069e35d9e77ce8afa33800915 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 4 Jun 2013 07:53:33 +0200 Subject: [PATCH 057/268] the next generation of config???? --- linspector.minimal.NG.json | 101 +++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 linspector.minimal.NG.json diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json new file mode 100644 index 0000000..38e9356 --- /dev/null +++ b/linspector.minimal.NG.json @@ -0,0 +1,101 @@ +{ + "filters": + { + "email": + { + "command": "email @member @+message", + "comment": "Sends an E-Mail to the member.", + "priority": 1 + } + }, + "members": + { + "hanez": + { + "name": "Johannes Findeisen", + "comment": "Just a nerd doing admin stuff...", + "filters": {"email": "you@hanez.org"} + } + }, + "periods": { + "short": {"seconds": 5, "comment": "Interval job; every 10 seconds"}, + "middle": {"seconds": 60, "comment": "Interval job; every 60 seconds"}, + "long": {"minutes": 2, "comment": "Interval job; every 2 minutes"} + }, + "hostgroups": + { + "group1": + { + "members": ["hanez"], + "hosts": ["a.systemchaos.org", "b.systemchaos.org"], + "services": { + "ping":[{ "args": { }, + "fails": { "warning": "100ms", "critical": "150ms" }, + "period": "short", + "threshold": 10, + "parser": { "class": "shell", "line": 2, "col": 5 }}], + "tcpconnect":[{ "args": { "port": 80 }, + "period": "middle", + "fails": { }, + "threshold": 2, + "parser": { "class": "none" }}], + "tcpconnect":[{ "args": { "port": 25 }, + "period": "long", + "fails": { }, + "threshold": 2, + "parser": { "class": "none" }}], + "tcpconnect":[{ "args": { "port": 110 }, + "period": "long", + "fails": { }, + "threshold": 2, + "parser": { "class": "none" }}], + "httpget":[{ "args": { "port": 80, "path": "/status.cgi", "string": "

I am up!

" }, + "period": "long", + "fails": { }, + "threshold": 2, + "parser": { "class": "none" }, + "comment": "Just a string grep"}] + } + }, + "group2": + { + "members": ["hanez"], + "hosts": ["x.systemchaos.org", "y.systemchaos.org"], + "services": { + "ping":[{ "args": { }, + "fails": { "warning": "100ms", "critical": "150ms" }, + "period": "short", + "threshold": 10, + "parser": { "class": "shell", "line": 2, "col": 5 }}], + "tcpconnect":[{ "args": { "port": 2342 }, + "period": "long", + "fails": { }, + "threshold": 2, + "parser": { "class": "none" }}] + } + }, + "group3": + { + "members": ["hanez"], + "hosts": ["master.systemchaos.org"], + "services": { + "ping":[{ "args": { }, + "fails": { "warning": "60ms", "critical": "10ms" }, + "period": "short", + "threshold": 10, + "parser": { "class": "shell", "line": 2, "col": 5 }}] + } + } + }, + "layouts": { + "production": {"hostgroups": ["group1"], "enabled": true}, + "critical": {"hostgroups": ["group3"], "enabled": false}, + "all": {"hostgroups": ["group1", "group2", "group3"], "enabled": false} + }, + "core": { + "max_logfile_size": 1024000, + "max_logfile_count": 4, + "max_worker_threads": 8, + "enabled_services": ["ping", "tcpconnect", "httpget", "shell", "ssh"] + } +} \ No newline at end of file From 94f20b81285003ffb543c2c1ce4e0238995088b3 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 4 Jun 2013 22:04:29 +0200 Subject: [PATCH 058/268] fixed invalid key clash in linspector.minimal.NG.json, removed unnessesary stuff (null or none definitions) --- linspector.minimal.NG.json | 250 ++++++++++++++++++++++--------------- 1 file changed, 152 insertions(+), 98 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index 38e9356..4087583 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -1,101 +1,155 @@ { - "filters": - { - "email": - { - "command": "email @member @+message", - "comment": "Sends an E-Mail to the member.", - "priority": 1 - } - }, - "members": - { - "hanez": - { - "name": "Johannes Findeisen", - "comment": "Just a nerd doing admin stuff...", - "filters": {"email": "you@hanez.org"} - } - }, - "periods": { - "short": {"seconds": 5, "comment": "Interval job; every 10 seconds"}, - "middle": {"seconds": 60, "comment": "Interval job; every 60 seconds"}, - "long": {"minutes": 2, "comment": "Interval job; every 2 minutes"} - }, - "hostgroups": - { - "group1": - { - "members": ["hanez"], - "hosts": ["a.systemchaos.org", "b.systemchaos.org"], - "services": { - "ping":[{ "args": { }, - "fails": { "warning": "100ms", "critical": "150ms" }, - "period": "short", - "threshold": 10, - "parser": { "class": "shell", "line": 2, "col": 5 }}], - "tcpconnect":[{ "args": { "port": 80 }, - "period": "middle", - "fails": { }, - "threshold": 2, - "parser": { "class": "none" }}], - "tcpconnect":[{ "args": { "port": 25 }, - "period": "long", - "fails": { }, - "threshold": 2, - "parser": { "class": "none" }}], - "tcpconnect":[{ "args": { "port": 110 }, - "period": "long", - "fails": { }, - "threshold": 2, - "parser": { "class": "none" }}], - "httpget":[{ "args": { "port": 80, "path": "/status.cgi", "string": "

I am up!

" }, - "period": "long", - "fails": { }, - "threshold": 2, - "parser": { "class": "none" }, - "comment": "Just a string grep"}] - } - }, - "group2": - { - "members": ["hanez"], - "hosts": ["x.systemchaos.org", "y.systemchaos.org"], - "services": { - "ping":[{ "args": { }, - "fails": { "warning": "100ms", "critical": "150ms" }, - "period": "short", - "threshold": 10, - "parser": { "class": "shell", "line": 2, "col": 5 }}], - "tcpconnect":[{ "args": { "port": 2342 }, - "period": "long", - "fails": { }, - "threshold": 2, - "parser": { "class": "none" }}] - } - }, - "group3": - { - "members": ["hanez"], - "hosts": ["master.systemchaos.org"], - "services": { - "ping":[{ "args": { }, - "fails": { "warning": "60ms", "critical": "10ms" }, - "period": "short", - "threshold": 10, - "parser": { "class": "shell", "line": 2, "col": 5 }}] - } - } - }, - "layouts": { - "production": {"hostgroups": ["group1"], "enabled": true}, - "critical": {"hostgroups": ["group3"], "enabled": false}, - "all": {"hostgroups": ["group1", "group2", "group3"], "enabled": false} - }, - "core": { - "max_logfile_size": 1024000, - "max_logfile_count": 4, - "max_worker_threads": 8, - "enabled_services": ["ping", "tcpconnect", "httpget", "shell", "ssh"] + "filters":{ + "email":{ + "command":"email @member @+message", + "comment":"Sends an E-Mail to the member.", + "priority":1 } + }, + "members":{ + "hanez":{ + "name":"Johannes Findeisen", + "comment":"Just a nerd doing admin stuff...", + "filters":{ "email":"you@hanez.org" } + } + }, + "periods":{ + "short":{ + "seconds":5, + "comment":"Interval job; every 10 seconds" + }, + "middle":{ + "seconds":60, + "comment":"Interval job; every 60 seconds" + }, + "long":{ + "minutes":2, + "comment":"Interval job; every 2 minutes" + } + }, + "hostgroups":{ + "group1":{ + "members":[ + "hanez" + ], + "hosts":[ + "a.systemchaos.org", + "b.systemchaos.org" + ], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods": ["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":80 }, + "periods": ["middle"], + "threshold":2, + }, + { + "class":"tcpconnect", + "args":{ "port":25 }, + "periods":["long"], + "threshold":2, + }, + { + "class":"tcpconnect", + "args":{ "port":110 }, + "periods": ["long"], + "threshold":2, + }, + { + "class":"httpget", + "args":{ "port":80, "path":"/status.cgi", "string":"

I am up!

" }, + "periods": ["long"], + "threshold":2, + "parser":{ "class":"StringCompare", "args": { "string":"

I am up!

" } }, + "comment":"Just a string grep" + } + ] + } + }, + "group2":{ + "members":["hanez"], + "hosts":["x.systemchaos.org", "y.systemchaos.org"], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods":["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":2342 }, + "periods":["long"], + "threshold":2 + } + ] + }, + "group3":{ + "members":[ + "hanez" + ], + "hosts":[ + "master.systemchaos.org" + ], + "services":[ + { + "class":"ping", + "fails":{ + "warning":"60ms", + "critical":"10ms" + }, + "periods":[ + "short" + ], + "threshold":10, + "parser":{ + "class":"shell", + "line":2, + "col":5 + } + } + ] + }, + "layouts":{ + "production":{ + "hostgroups":[ + "group1" + ], + "enabled":true + }, + "critical":{ + "hostgroups":[ + "group3" + ], + "enabled":false + }, + "all":{ + "hostgroups":[ + "group1", + "group2", + "group3" + ], + "enabled":false + } + }, + "core":{ + "max_logfile_size":1024000, + "max_logfile_count":4, + "max_worker_threads":8, + "enabled_services":[ + "ping", + "tcpconnect", + "httpget", + "shell", + "ssh" + ] + } } \ No newline at end of file From 0f5cd0b585f0442b4472d9b46364e12be773b156 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 4 Jun 2013 22:48:45 +0200 Subject: [PATCH 059/268] fixed the json... again --- linspector.minimal.NG.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index 4087583..da25196 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -48,19 +48,19 @@ "class":"tcpconnect", "args":{ "port":80 }, "periods": ["middle"], - "threshold":2, + "threshold":2 }, { "class":"tcpconnect", "args":{ "port":25 }, "periods":["long"], - "threshold":2, + "threshold":2 }, { "class":"tcpconnect", "args":{ "port":110 }, "periods": ["long"], - "threshold":2, + "threshold":2 }, { "class":"httpget", @@ -152,4 +152,4 @@ "ssh" ] } -} \ No newline at end of file +} From 2676360cedc8e105c2e8eb1254fb7d700c161a35 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 4 Jun 2013 23:06:05 +0200 Subject: [PATCH 060/268] basic parser structure --- lib/parser/parser.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/parser/parser.py b/lib/parser/parser.py index e69de29..7e4fb1c 100644 --- a/lib/parser/parser.py +++ b/lib/parser/parser.py @@ -0,0 +1,14 @@ + +class Parser: + def __init__(self): + pass + + def parse_data(self, data): + self.pre_parse(data) + return self.generate_parse_result(data) + + def pre_parse(self, data): + pass + + def generate_parse_result(self, result): + pass From 737dc26a5d831aec4e9240bbd4e6971953df5bf5 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 4 Jun 2013 23:07:05 +0200 Subject: [PATCH 061/268] basic parser structure --- lib/parser/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/parser/parser.py b/lib/parser/parser.py index 7e4fb1c..4c8feb4 100644 --- a/lib/parser/parser.py +++ b/lib/parser/parser.py @@ -4,8 +4,8 @@ class Parser: pass def parse_data(self, data): - self.pre_parse(data) - return self.generate_parse_result(data) + self.pre_parse(data) + return self.generate_parse_result(data) def pre_parse(self, data): pass From a516b3dd1c4916a92bb0e9fe59100ac3443d9ef5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 4 Jun 2013 23:13:18 +0200 Subject: [PATCH 062/268] added service class --- lib/service/service.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 lib/service/service.py diff --git a/lib/service/service.py b/lib/service/service.py new file mode 100644 index 0000000..740d930 --- /dev/null +++ b/lib/service/service.py @@ -0,0 +1,17 @@ + +class Service: + def __init__(self, args): + self.args = args + pass + + def execute(self): + pass + + def pre_execute(self): + pass + + def parse_result(self): + pass + + def handle_result(self): + pass \ No newline at end of file From 53e2f2aad035b8fedb2ae794dd3846c45b42f78f Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 4 Jun 2013 23:31:24 +0200 Subject: [PATCH 063/268] changed behavior of service api --- lib/service/service.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/service/service.py b/lib/service/service.py index 740d930..6de8e3c 100644 --- a/lib/service/service.py +++ b/lib/service/service.py @@ -1,9 +1,14 @@ class Service: - def __init__(self, args): - self.args = args + def __init__(self): pass + def _execute(self): + self.pre_execute() + self.execute() + self.parse_result() + self.handle_result() + def execute(self): pass From 90c41027c69486d83b39dade0acef2d4dae7add7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 00:09:24 +0200 Subject: [PATCH 064/268] added shell service and fixed service --- lib/service/service.py | 9 ++++----- lib/service/shell.py | 20 +++++++++++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/service/service.py b/lib/service/service.py index 6de8e3c..1664152 100644 --- a/lib/service/service.py +++ b/lib/service/service.py @@ -1,14 +1,13 @@ - class Service: - def __init__(self): - pass + def __init__(self, parser): + self.parser = parser def _execute(self): self.pre_execute() self.execute() self.parse_result() self.handle_result() - + def execute(self): pass @@ -16,7 +15,7 @@ class Service: pass def parse_result(self): - pass + self.parser._parse() def handle_result(self): pass \ No newline at end of file diff --git a/lib/service/shell.py b/lib/service/shell.py index 234b714..7b7e470 100644 --- a/lib/service/shell.py +++ b/lib/service/shell.py @@ -1,4 +1,18 @@ """ -The shell service. This is for executing services as shell commands and don't use a builtin function. This is useful to -be free to do what you want. -""" \ No newline at end of file +The shell service. This is for executing services as shell commands +and don't use a builtin function. This is useful to be free to do what you want. +""" + +from service import Service + + +class ShellService(Service): + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) + if "command" in kwargs: + self.command = kwargs["command"] + else: + log.w("There is no command") + + def execute(self): + self.command.call() \ No newline at end of file From 22fde832aec5a109f5f338edf9aefd66c82b9975 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 02:02:40 +0200 Subject: [PATCH 065/268] json changes --- linspector.minimal.NG.json | 52 ++++++++++---------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index da25196..958466f 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -67,7 +67,7 @@ "args":{ "port":80, "path":"/status.cgi", "string":"

I am up!

" }, "periods": ["long"], "threshold":2, - "parser":{ "class":"StringCompare", "args": { "string":"

I am up!

" } }, + "parser":{ "class":"grep", "args": { "string":"

I am up!

" } }, "comment":"Just a string grep" } ] @@ -93,63 +93,37 @@ ] }, "group3":{ - "members":[ - "hanez" - ], - "hosts":[ - "master.systemchaos.org" - ], + "members":[ "hanez" ], + "hosts":[ "master.systemchaos.org" ], "services":[ { - "class":"ping", - "fails":{ - "warning":"60ms", - "critical":"10ms" - }, - "periods":[ - "short" - ], + "class":"ssh", + "args":{ "port":23, "command":"df" }, + "fails":{ "warning":"80%", "critical":"90%" }, + "periods":[ "long" ], "threshold":10, - "parser":{ - "class":"shell", - "line":2, - "col":5 - } + "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, + { "class":"grep", "line": "/dev/sda2", "col":5 } ] } ] }, "layouts":{ "production":{ - "hostgroups":[ - "group1" - ], + "hostgroups":[ "group1" ], "enabled":true }, "critical":{ - "hostgroups":[ - "group3" - ], + "hostgroups":[ "group3" ], "enabled":false }, "all":{ - "hostgroups":[ - "group1", - "group2", - "group3" - ], + "hostgroups":[ "group1", "group2", "group3" ], "enabled":false } }, "core":{ "max_logfile_size":1024000, "max_logfile_count":4, - "max_worker_threads":8, - "enabled_services":[ - "ping", - "tcpconnect", - "httpget", - "shell", - "ssh" - ] + "max_worker_threads":8 } } From e39339a10f0988eca022ac8947150cb20adf0f53 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 02:17:07 +0200 Subject: [PATCH 066/268] json changes --- linspector.minimal.NG.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index 958466f..a0d1922 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -64,11 +64,11 @@ }, { "class":"httpget", - "args":{ "port":80, "path":"/status.cgi", "string":"

I am up!

" }, + "args":{ "port":80, "path":"/status.cgi" }, "periods": ["long"], "threshold":2, - "parser":{ "class":"grep", "args": { "string":"

I am up!

" } }, - "comment":"Just a string grep" + "parser":{ "class":"grep", "string": "

I am up!

" }, + "comment": "Just a string grep" } ] } From 8bcac96942cc5628b51b5ad415568f1041aaade2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 04:18:37 +0200 Subject: [PATCH 067/268] just some config object cleanups --- lib/config/config.py | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/lib/config/config.py b/lib/config/config.py index ac72699..4ad862f 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -1,11 +1,9 @@ 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 * +#from hostgroups import parseHostGroupList +#from layouts import parseLayoutList class Config: @@ -17,21 +15,12 @@ class Config: 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, log) - - self.periods = parsePeriodList(self.dict['periods'],log) - - self.hosts = parseHostList(self.dict['hosts'], self.services, log) - - self.hostgroups = parseHostGroupList(self.dict['hostgroups'], - self.hosts, - self.members, - self.periods, - self.services, - log) + self.periods = parsePeriodList(self.dict['periods'], log) + #self.hostgroups = parseHostGroupList(self.dict['hostgroups'], + # self.members, + # self.periods, + # log) #self.layouts = LayoutList(self.dict['layouts'], self.hostgroups) \ No newline at end of file From 61737bfec080e99a0effa82544abe0f4b0e7e61d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 04:19:27 +0200 Subject: [PATCH 068/268] major json update to show more complex configurations and additional parameters --- linspector.minimal.NG.json | 261 ++++++++++++++++++++----------------- 1 file changed, 138 insertions(+), 123 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index a0d1922..512b6ca 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -1,129 +1,144 @@ { - "filters":{ - "email":{ - "command":"email @member @+message", - "comment":"Sends an E-Mail to the member.", - "priority":1 - } - }, - "members":{ - "hanez":{ - "name":"Johannes Findeisen", - "comment":"Just a nerd doing admin stuff...", - "filters":{ "email":"you@hanez.org" } - } - }, - "periods":{ - "short":{ - "seconds":5, - "comment":"Interval job; every 10 seconds" - }, - "middle":{ - "seconds":60, - "comment":"Interval job; every 60 seconds" - }, - "long":{ - "minutes":2, - "comment":"Interval job; every 2 minutes" - } - }, - "hostgroups":{ - "group1":{ - "members":[ - "hanez" - ], - "hosts":[ - "a.systemchaos.org", - "b.systemchaos.org" - ], - "services":[ - { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods": ["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } - }, - { - "class":"tcpconnect", - "args":{ "port":80 }, - "periods": ["middle"], - "threshold":2 - }, - { - "class":"tcpconnect", - "args":{ "port":25 }, - "periods":["long"], - "threshold":2 - }, - { - "class":"tcpconnect", - "args":{ "port":110 }, - "periods": ["long"], - "threshold":2 - }, - { - "class":"httpget", - "args":{ "port":80, "path":"/status.cgi" }, - "periods": ["long"], - "threshold":2, - "parser":{ "class":"grep", "string": "

I am up!

" }, - "comment": "Just a string grep" + "filters":{ + "email":{ + "command":"email @member @+message", + "comment":"Sends an E-Mail to the member.", + "priority":1 } - ] - } - }, - "group2":{ - "members":["hanez"], - "hosts":["x.systemchaos.org", "y.systemchaos.org"], - "services":[ - { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods":["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } - }, - { - "class":"tcpconnect", - "args":{ "port":2342 }, - "periods":["long"], - "threshold":2 - } - ] - }, - "group3":{ - "members":[ "hanez" ], - "hosts":[ "master.systemchaos.org" ], - "services":[ - { - "class":"ssh", - "args":{ "port":23, "command":"df" }, - "fails":{ "warning":"80%", "critical":"90%" }, - "periods":[ "long" ], - "threshold":10, - "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, - { "class":"grep", "line": "/dev/sda2", "col":5 } ] - } - ] - }, - "layouts":{ - "production":{ - "hostgroups":[ "group1" ], - "enabled":true }, - "critical":{ - "hostgroups":[ "group3" ], - "enabled":false + "members":{ + "hanez":{ + "name":"Johannes Findeisen", + "comment":"Just a nerd doing admin stuff...", + "parent": "darth", + "filters":{ "email":"you@hanez.org" } + }, + "darth":{ + "name":"Darth Vader", + "comment":"The father", + "filters":{ "email":"darth.vader@hanez.org" } + } }, - "all":{ - "hostgroups":[ "group1", "group2", "group3" ], - "enabled":false + "periods":{ + "short":{ + "seconds":5, + "comment":"Interval job; every 10 seconds" + }, + "middle":{ + "seconds":60, + "comment":"Interval job; every 60 seconds" + }, + "long":{ + "minutes":2, + "comment":"Interval job; every 2 minutes" + } + }, + "hostgroups":{ + "group1":{ + "members":[ "hanez" ], + "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], + "parents": [ "network" ], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods": ["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":80 }, + "periods": ["middle"], + "threshold":2 + }, + { + "class":"tcpconnect", + "args":{ "port":25 }, + "periods":["long"], + "threshold":2 + }, + { + "class":"tcpconnect", + "args":{ "port":110 }, + "periods": ["long"], + "threshold":2 + }, + { + "class":"htmlcontent", + "args":{ "port":80, "path":"/status.cgi" }, + "periods": ["long"], + "threshold":2, + "parser":{ "class":"grep", "string": "

I am up!

" }, + "comment": "Just a string grep" + } + ] + }, + "group2":{ + "members":["hanez"], + "hosts":["x.systemchaos.org", "y.systemchaos.org"], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods":["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":2342 }, + "periods":["long"], + "threshold":2 + } + ] + }, + "group3":{ + "members":[ "hanez" ], + "hosts":[ "master.systemchaos.org" ], + "services":[ + { + "class":"ssh", + "args":{ "port": 23, "command": "df", "username": "hanez", "password": "secret", "key": "~/.ssh/id_rsa" }, + "fails":{ "warning":"80%", "critical":"90%" }, + "periods":[ "long" ], + "threshold":10, + "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, + [{ "class":"grep", "line": "/dev/sda2", "col":5 }, { "class":"grep", "line": "/dev/sda2", "col":5 }]] + } + ] + }, + "network":{ + "members":[ "hanez" ], + "hosts":[ "router.systemchaos.org" ], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods": ["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + } + ] + } + }, + "layouts":{ + "production":{ + "hostgroups": [ "group1" ], + "enabled": true + }, + "critical":{ + "hostgroups": [ "group3" ], + "enabled": false + }, + "all":{ + "hostgroups": [ "group1", "group2", "group3" ], + "enabled": false + } + }, + "core":{ + "max_logfile_size": 1024000, + "max_logfile_count": 4, + "max_worker_threads": 8 } - }, - "core":{ - "max_logfile_size":1024000, - "max_logfile_count":4, - "max_worker_threads":8 - } } From 132ce81d053293f052e1acccbc5d75adae1b8413 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 04:20:26 +0200 Subject: [PATCH 069/268] added some code to the service classes; no working code; mostly boilerplate... --- lib/service/htmlcontent.py | 43 +++++++++++++++++++++++++++++++++- lib/service/service.py | 4 +++- lib/service/shell.py | 3 +-- lib/service/ssh.py | 42 +++++++++++++++++++++++++++++++-- lib/service/tcpconnect.py | 48 ++++++++++++++++++++------------------ 5 files changed, 111 insertions(+), 29 deletions(-) diff --git a/lib/service/htmlcontent.py b/lib/service/htmlcontent.py index 6d9580c..37a7554 100644 --- a/lib/service/htmlcontent.py +++ b/lib/service/htmlcontent.py @@ -1,5 +1,8 @@ """ The htmlcontent service in pure Python. STUPID NAME!!! + +This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and +not use a parser. """ # http://pycurl.sourceforge.net/ --- seems old... @@ -7,4 +10,42 @@ The htmlcontent service in pure Python. STUPID NAME!!! # # maybe better: http://docs.python.org/2/library/urllib.html # -# or look at tcpconnect.py! could be useful to. \ No newline at end of file +# or look at tcpconnect.py! could be useful to. + +import socket +import sys +from service import Service + + +class HtmlcontentService(Service): + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) + + if "string" in kwargs: + self.string = kwargs["string"] + else: + log.w("There is no string set to match") + + def execute(self): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(1) + + try: + sock.connect((self.host, self.port)) + except socket.error, msg: + sys.stderr.write("[ERROR] %s\n" % msg[1]) + sys.exit(2) + + sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (self.path, self.host)) + + data = sock.recv(1024) + string = "" + while len(data): + string = string + data + data = sock.recv(1024) + sock.close() + #print string + # make substring in string compare here. regex or so... diff --git a/lib/service/service.py b/lib/service/service.py index 1664152..0ec3ea8 100644 --- a/lib/service/service.py +++ b/lib/service/service.py @@ -1,6 +1,8 @@ class Service: - def __init__(self, parser): + def __init__(self, host, parser): + self.host = host self.parser = parser + self.errorcode = 0 def _execute(self): self.pre_execute() diff --git a/lib/service/shell.py b/lib/service/shell.py index 7b7e470..097ac35 100644 --- a/lib/service/shell.py +++ b/lib/service/shell.py @@ -1,6 +1,5 @@ """ -The shell service. This is for executing services as shell commands -and don't use a builtin function. This is useful to be free to do what you want. +The shell service. This is for executing local shell commands and retrieve the output. """ from service import Service diff --git a/lib/service/ssh.py b/lib/service/ssh.py index 123c460..7b94c02 100644 --- a/lib/service/ssh.py +++ b/lib/service/ssh.py @@ -1,5 +1,43 @@ """ -The ssh service in pure Python. +The ssh service This is for executing remote shell commands and retrieve the output. + +This service is using paramiko (http://www.lag.net/paramiko/). """ -# http://www.lag.net/paramiko/ \ No newline at end of file +import paramiko +import pprint +import os +from service import Service + + +class SshService(Service): + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) + if "command" in kwargs: + self.command = kwargs["command"] + else: + log.w("There is no command") + + def execute(self): + path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') + key = paramiko.RSAKey.from_private_key_file(path) + + client = paramiko.SSHClient() + client.get_host_keys().add('hanez.org', 'ssh-rsa', key) + pprint.pprint(client._host_keys) + + client.connect('hanez.org', username='hanez') + + #self.command.call() ist dann das: + stdin, stdout, stderr = client.exec_command('ls') + for line in stdout: + print '... ' + line.strip('\n') + client.close() + + +# def main(): +# # service = SshService(parser, log, command='uptime') +# return +# +# if __name__ == "__main__": +# main() \ No newline at end of file diff --git a/lib/service/tcpconnect.py b/lib/service/tcpconnect.py index 18fe5e7..2306b4b 100644 --- a/lib/service/tcpconnect.py +++ b/lib/service/tcpconnect.py @@ -1,33 +1,35 @@ """ -The tcpconnect service in pure Python. +The tcpconnect service. This is to check if a service on a specific port is reachable. + +This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and +not use a parser. """ import socket -import sys +from service import Service -HOST = 'linspector.org' -GET = '/index.html' -PORT = 80 -try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -except socket.error, msg: - sys.stderr.write("[ERROR] %s\n" % msg[1]) - sys.exit(1) +class TcpconnectService(Service): + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) -try: - sock.connect((HOST, PORT)) -except socket.error, msg: - sys.stderr.write("[ERROR] %s\n" % msg[1]) - sys.exit(2) + if "port" in kwargs: + self.port = kwargs["port"] + else: + log.w("There is no port set") -sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (GET, HOST)) + def execute(self, log): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + except socket.error, msg: + log.w("%s\n" % msg[1]) + self.errorcode = 1 -data = sock.recv(1024) -string = "" -while len(data): - string = string + data - data = sock.recv(1024) -sock.close() + try: + sock.connect((self.host, self.port)) + except socket.error, msg: + log.w("%s\n" % msg[1]) + self.errorcode = 2 -print string + sock.close() + return \ No newline at end of file From c591f1bade4afa19e9ba3d0eda6d04fc87f9f16f Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 04:23:47 +0200 Subject: [PATCH 070/268] version bump to 0.4 --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 58ed28a..1699eaf 100755 --- a/linspector +++ b/linspector @@ -1,6 +1,6 @@ #!/usr/bin/python2.7 -tt -__version__ = "0.3/TETRIS" +__version__ = "0.4/TETRIS" import argparse import time From 6d6bbbc8e4bcbbe7549db0bbf27787447b3dad8d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 05:49:09 +0200 Subject: [PATCH 071/268] some more config parameters added --- linspector.minimal.NG.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json index 512b6ca..2031f78 100644 --- a/linspector.minimal.NG.json +++ b/linspector.minimal.NG.json @@ -65,8 +65,8 @@ "threshold":2 }, { - "class":"htmlcontent", - "args":{ "port":80, "path":"/status.cgi" }, + "class":"http", + "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params": { "foo": 1, "bar": 2 }, "protocol": "https"}, "periods": ["long"], "threshold":2, "parser":{ "class":"grep", "string": "

I am up!

" }, From 97f479dc09d7f3a288bbbcd5e15cd45fbc203714 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 05:50:11 +0200 Subject: [PATCH 072/268] moved htmlcontent service to http. this service is really for fetching data over http. i switched from socket stuff to urllib too... --- lib/service/http.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 lib/service/http.py diff --git a/lib/service/http.py b/lib/service/http.py new file mode 100644 index 0000000..a7cb3b3 --- /dev/null +++ b/lib/service/http.py @@ -0,0 +1,54 @@ +""" +The http service. + +This is for checking the availability and output of HTTP services. Basic HTTP +content could be fetched and compared.HTTPS is not validating the server certificate! + +This should just return 0 on success and NOT 0 on error. Just to make internals generic +to just report this code and not use a parser. +""" + +import urllib +from service import Service + + +class HttpService(Service): + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) + + if "string" in kwargs: + self.string = kwargs["string"] + else: + log.w("There is no string set to match") + + if "method" in kwargs: + self.method = kwargs["method"] + else: + self.method = "get" + + if "params" in kwargs: + self.params = kwargs["params"] + + if "path" in kwargs: + self.path = kwargs["path"] + elif: + self.path = "/" + + if "port" in kwargs: + self.port = kwargs["port"] + else: + self.port = "80" + + if "protocol" in kwargs: + self.protocol = kwargs["protocol"] + else: + self.protocol = "http" + + def execute(self): + params = urllib.urlencode(self.params) + if self.method is "get": + f = urllib.urlopen(self.protocol + "://" + self.host + ":" + self.port + self.path + "?%s" % params) + elif self.method is "post": + f = urllib.urlopen(self.protocol + "://" + self.host + ":" + self.port + self.path, params) + + #print f.read() \ No newline at end of file From 36fd02c6f9d9f75a4fd2f7fabd1f3ae2b239cb32 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 05:54:16 +0200 Subject: [PATCH 073/268] uups... ;) --- lib/service/http.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/service/http.py b/lib/service/http.py index a7cb3b3..f967ad4 100644 --- a/lib/service/http.py +++ b/lib/service/http.py @@ -31,7 +31,7 @@ class HttpService(Service): if "path" in kwargs: self.path = kwargs["path"] - elif: + else: self.path = "/" if "port" in kwargs: From 7a550f7f4c084ad51654def253ab0827cbaee714 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 05:54:48 +0200 Subject: [PATCH 074/268] deleted htmlcontent service --- lib/service/htmlcontent.py | 51 -------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 lib/service/htmlcontent.py diff --git a/lib/service/htmlcontent.py b/lib/service/htmlcontent.py deleted file mode 100644 index 37a7554..0000000 --- a/lib/service/htmlcontent.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -The htmlcontent service in pure Python. STUPID NAME!!! - -This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and -not use a parser. -""" - -# http://pycurl.sourceforge.net/ --- seems old... -# http://www.angryobjects.com/2011/10/15/http-with-python-pycurl-by-example/ -# -# maybe better: http://docs.python.org/2/library/urllib.html -# -# or look at tcpconnect.py! could be useful to. - -import socket -import sys -from service import Service - - -class HtmlcontentService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - - if "string" in kwargs: - self.string = kwargs["string"] - else: - log.w("There is no string set to match") - - def execute(self): - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - except socket.error, msg: - sys.stderr.write("[ERROR] %s\n" % msg[1]) - sys.exit(1) - - try: - sock.connect((self.host, self.port)) - except socket.error, msg: - sys.stderr.write("[ERROR] %s\n" % msg[1]) - sys.exit(2) - - sock.send("GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (self.path, self.host)) - - data = sock.recv(1024) - string = "" - while len(data): - string = string + data - data = sock.recv(1024) - sock.close() - #print string - # make substring in string compare here. regex or so... From 686759dd9696017897fafc3b3bceedf496101e62 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 06:09:55 +0200 Subject: [PATCH 075/268] added errormessage to service --- lib/service/service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/service/service.py b/lib/service/service.py index 0ec3ea8..89f02a2 100644 --- a/lib/service/service.py +++ b/lib/service/service.py @@ -3,6 +3,7 @@ class Service: self.host = host self.parser = parser self.errorcode = 0 + self.errormessage = "No Error!" def _execute(self): self.pre_execute() From 61d7e17dc952dd391a717502f296e1c208e6987b Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 06:17:35 +0200 Subject: [PATCH 076/268] added a newline... hrhrhrhrhrhr... insider! --- linspector | 1 + 1 file changed, 1 insertion(+) diff --git a/linspector b/linspector index 1699eaf..2eb01db 100755 --- a/linspector +++ b/linspector @@ -13,6 +13,7 @@ from apscheduler.scheduler import Scheduler DEFAULT_CONFIG = "./linspector.minimal.json" + def parseArgs(): parser = argparse.ArgumentParser( description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", From 533cf02c10a5b68330aeb90ee00c56e1f474d5ff Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 06:22:38 +0200 Subject: [PATCH 077/268] moved NG json to default file --- linspector | 5 +- linspector.json | 338 ++++++++++++++----------------------- linspector.minimal.NG.json | 144 ---------------- linspector.old.json | 232 +++++++++++++++++++++++++ 4 files changed, 359 insertions(+), 360 deletions(-) delete mode 100644 linspector.minimal.NG.json create mode 100644 linspector.old.json diff --git a/linspector b/linspector index 2eb01db..4a9d4f9 100755 --- a/linspector +++ b/linspector @@ -1,6 +1,7 @@ #!/usr/bin/python2.7 -tt __version__ = "0.4/TETRIS" +__default_config__ = "./linspector.json" import argparse import time @@ -11,8 +12,6 @@ from lib.core.logger import Logger from lib.config.config import Config from apscheduler.scheduler import Scheduler -DEFAULT_CONFIG = "./linspector.minimal.json" - def parseArgs(): parser = argparse.ArgumentParser( @@ -23,7 +22,7 @@ def parseArgs(): parser.add_argument("action", choices=["start", "stop", "restart", "attach"], help="defines if linspector should beeing attached, started, stopped or restarted.") parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) - parser.add_argument("-c", "--config", default=DEFAULT_CONFIG, + parser.add_argument("-c", "--config", default=__default_config__, help="select configfile to use") parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", help="set logfile to use") diff --git a/linspector.json b/linspector.json index 82ceb0c..2031f78 100644 --- a/linspector.json +++ b/linspector.json @@ -1,230 +1,142 @@ { - "services": - { - "discusage": {"command": "ssh @host df -a @device", "parser": "df"}, - "load": {"command": "ssh @host uptime"}, - "dirsize": { "command": "ssh @host du -chs @path"}, - "filesize": {"command": "ssh @host du -chs @path"}, - "loggedinusercount": {"command": "ssh @host who | wc -l"}, - "loggedinusers": {"command": "ssh @host who"}, - "swapusage": {"command": "ssh @host cat /proc/swaps"}, - "processcount": {"command": "ssh @host ps ax | wc -l"}, - "processcountbyname": {"command": "ssh @host ps ax | grep @name | wc -l"}, - "fileage": {"command": "ssh @host ls -l @file"}, - "ping": {"command": "ping @host"}, - "snmpget": {"command": "snmpget -v1 -c public $oid"}, - "busy_waiting": {"command": "sleep 3600"}, - "htmlcontent": {"command": "wget -qO- @url", "comment": "Get HTML Content for a string lookup."} - }, - "filters": - { - "email": - { - "command": "/usr/bin/warn_the_admin_mail @member @+message", - "comment": "Sends an E-Mail to the member.", - "priority": 1 - }, - "sms": - { - "command": "/usr/bin/warn_the_admin_sms @member @+message", - "comment": "Sends a Short Message to the member.", - "priority": 0 - }, - "foo": - { - "command": "/usr/bin/warn_the_admin_foo @member @+message", - "priority": 500 - }, - "mongowriter": - { - "command": "./plugins/mongowriter.py @+message localhost 27017 linspector123", - "priority": 1000 + "filters":{ + "email":{ + "command":"email @member @+message", + "comment":"Sends an E-Mail to the member.", + "priority":1 } }, - "members": - { - "hanez": - { - "name": "Johannes Findeisen", - "comment": "Just a nerd doing admin stuff...", - "parent": "admin", - "filters": - { - "email": "you@hanez.org", - "sms": "+23345567" - } + "members":{ + "hanez":{ + "name":"Johannes Findeisen", + "comment":"Just a nerd doing admin stuff...", + "parent": "darth", + "filters":{ "email":"you@hanez.org" } }, - "linspector": - { - "name": "Linspector BOT", - "comment": "Botty Botsen...", - "parent": "admin", - "filters": - { - "email": "botty@hanez.org", - "sms": "+23345567213123" - } - }, - "unixpeople": - { - "name": "Hanna Findeisen", - "comment": "Master of UNIX", - "parent": "admin", - "filters": - { - "email": "master@hanez.org", - "sms": "+2334556733333" - } - }, - "admin": - { - "name": "Peter Hansen", - "comment": "The son of Hans-Peter Hansen", - "parent": "ultraadmin", - "filters": - { - "email": "admin@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ultraadmin": - { - "name": "Hans-Peter Hansen (CEO)", - "comment": "The guru of the Datacenter", - "parent": "darthvader", - "filters": - { - "email": "bofh@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "darthvader": - { - "name": "Darth Vader", - "comment": "The Father", - "filters": - { - "email": "darth.vader@systemchaos.org" - } - }, - "jens": - { - "name": "Jens Larssen", - "comment": "Our network guru", - "filters": - { - "email": "jens@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ruff": - { - "name": "Ruffn Buffn", - "filters": - { - "sms": "+23343457" - } - }, - "mongowriter": - { - "name": "MongoDB Database writer plugin", - "filters": - { - "mongowriter": "localhost" - } + "darth":{ + "name":"Darth Vader", + "comment":"The father", + "filters":{ "email":"darth.vader@hanez.org" } } }, - "periods": - { - "twentyfourseven": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "hour": "*", - "minute": "*/1", - "second": "0", - "comment": "Cron Job / Every minute" + "periods":{ + "short":{ + "seconds":5, + "comment":"Interval job; every 10 seconds" }, - "do_every_x_times" : { - "days": 0, - "weeks": 0, - "hours": 0, - "minutes": 0, - "seconds": 10, - "comment": "Interval Job / Every 10 seconds" + "middle":{ + "seconds":60, + "comment":"Interval job; every 60 seconds" }, - "next_christmas" : { - "date": "2013-12-24 20:00:00", - "comment": "Date Job / Just one day" + "long":{ + "minutes":2, + "comment":"Interval job; every 2 minutes" } }, - "hosts": - { - "hanez": - { - "host": "www.hanez.org", - "services": - { - "discusage": - [ - { "device": "/dev/sda1", "warning": "80%", "critical": "90%" }, - { "device": "/dev/sda2", "warning": "70%", "critical": "90%" }, - { "device": "/dev/sda3", "warning": "70GB", "critical": "90GB" } - ], - "load": - [ - { "warning": 8.00, "critical": 12.00 } - ], - "dirsize": - [ - { "path": "/var/log", "warning": 30000000, "critical": 40000000 } - ], - "processcount": - [ - { "warning": 3000, "critical": 3800 } - ], - "processcountbyname": - [ - { "name": "java", "warning": 100, "critical": 200 } - ], - "fileage": - [ - { "file": "/var/backup/server_1", "warning": 2, "critical": 3 } - ], - "htmlcontent": - [ - { "url": "@host/test.php", "content": "

Server up!

" } - ], - "ping": - [ - {} - ] - } + "hostgroups":{ + "group1":{ + "members":[ "hanez" ], + "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], + "parents": [ "network" ], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods": ["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":80 }, + "periods": ["middle"], + "threshold":2 + }, + { + "class":"tcpconnect", + "args":{ "port":25 }, + "periods":["long"], + "threshold":2 + }, + { + "class":"tcpconnect", + "args":{ "port":110 }, + "periods": ["long"], + "threshold":2 + }, + { + "class":"http", + "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params": { "foo": 1, "bar": 2 }, "protocol": "https"}, + "periods": ["long"], + "threshold":2, + "parser":{ "class":"grep", "string": "

I am up!

" }, + "comment": "Just a string grep" + } + ] + }, + "group2":{ + "members":["hanez"], + "hosts":["x.systemchaos.org", "y.systemchaos.org"], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods":["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + }, + { + "class":"tcpconnect", + "args":{ "port":2342 }, + "periods":["long"], + "threshold":2 + } + ] + }, + "group3":{ + "members":[ "hanez" ], + "hosts":[ "master.systemchaos.org" ], + "services":[ + { + "class":"ssh", + "args":{ "port": 23, "command": "df", "username": "hanez", "password": "secret", "key": "~/.ssh/id_rsa" }, + "fails":{ "warning":"80%", "critical":"90%" }, + "periods":[ "long" ], + "threshold":10, + "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, + [{ "class":"grep", "line": "/dev/sda2", "col":5 }, { "class":"grep", "line": "/dev/sda2", "col":5 }]] + } + ] + }, + "network":{ + "members":[ "hanez" ], + "hosts":[ "router.systemchaos.org" ], + "services":[ + { + "class":"ping", + "fails":{ "warning":"100ms", "critical":"150ms" }, + "periods": ["short"], + "threshold":10, + "parser":{ "class":"shell", "line":2, "col":5 } + } + ] } }, - "hostgroups": - { - "all": - { - "members": ["admin"], - "hosts": ["hanez"], - "parent": "network", - "threshold": 10, - "services": - { - "ping": ["do_every_x_times"] - } + "layouts":{ + "production":{ + "hostgroups": [ "group1" ], + "enabled": true + }, + "critical":{ + "hostgroups": [ "group3" ], + "enabled": false + }, + "all":{ + "hostgroups": [ "group1", "group2", "group3" ], + "enabled": false } }, - "layouts": {"production": {"hostgroups": ["all", "hanez", "network"], "enabled": true}, - "lazy": {"hostgroups": ["hanez", "ruff"], "enabled": false} - }, - "core": { + "core":{ "max_logfile_size": 1024000, "max_logfile_count": 4, "max_worker_threads": 8 diff --git a/linspector.minimal.NG.json b/linspector.minimal.NG.json deleted file mode 100644 index 2031f78..0000000 --- a/linspector.minimal.NG.json +++ /dev/null @@ -1,144 +0,0 @@ -{ - "filters":{ - "email":{ - "command":"email @member @+message", - "comment":"Sends an E-Mail to the member.", - "priority":1 - } - }, - "members":{ - "hanez":{ - "name":"Johannes Findeisen", - "comment":"Just a nerd doing admin stuff...", - "parent": "darth", - "filters":{ "email":"you@hanez.org" } - }, - "darth":{ - "name":"Darth Vader", - "comment":"The father", - "filters":{ "email":"darth.vader@hanez.org" } - } - }, - "periods":{ - "short":{ - "seconds":5, - "comment":"Interval job; every 10 seconds" - }, - "middle":{ - "seconds":60, - "comment":"Interval job; every 60 seconds" - }, - "long":{ - "minutes":2, - "comment":"Interval job; every 2 minutes" - } - }, - "hostgroups":{ - "group1":{ - "members":[ "hanez" ], - "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], - "parents": [ "network" ], - "services":[ - { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods": ["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } - }, - { - "class":"tcpconnect", - "args":{ "port":80 }, - "periods": ["middle"], - "threshold":2 - }, - { - "class":"tcpconnect", - "args":{ "port":25 }, - "periods":["long"], - "threshold":2 - }, - { - "class":"tcpconnect", - "args":{ "port":110 }, - "periods": ["long"], - "threshold":2 - }, - { - "class":"http", - "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params": { "foo": 1, "bar": 2 }, "protocol": "https"}, - "periods": ["long"], - "threshold":2, - "parser":{ "class":"grep", "string": "

I am up!

" }, - "comment": "Just a string grep" - } - ] - }, - "group2":{ - "members":["hanez"], - "hosts":["x.systemchaos.org", "y.systemchaos.org"], - "services":[ - { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods":["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } - }, - { - "class":"tcpconnect", - "args":{ "port":2342 }, - "periods":["long"], - "threshold":2 - } - ] - }, - "group3":{ - "members":[ "hanez" ], - "hosts":[ "master.systemchaos.org" ], - "services":[ - { - "class":"ssh", - "args":{ "port": 23, "command": "df", "username": "hanez", "password": "secret", "key": "~/.ssh/id_rsa" }, - "fails":{ "warning":"80%", "critical":"90%" }, - "periods":[ "long" ], - "threshold":10, - "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, - [{ "class":"grep", "line": "/dev/sda2", "col":5 }, { "class":"grep", "line": "/dev/sda2", "col":5 }]] - } - ] - }, - "network":{ - "members":[ "hanez" ], - "hosts":[ "router.systemchaos.org" ], - "services":[ - { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods": ["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } - } - ] - } - }, - "layouts":{ - "production":{ - "hostgroups": [ "group1" ], - "enabled": true - }, - "critical":{ - "hostgroups": [ "group3" ], - "enabled": false - }, - "all":{ - "hostgroups": [ "group1", "group2", "group3" ], - "enabled": false - } - }, - "core":{ - "max_logfile_size": 1024000, - "max_logfile_count": 4, - "max_worker_threads": 8 - } -} diff --git a/linspector.old.json b/linspector.old.json new file mode 100644 index 0000000..82ceb0c --- /dev/null +++ b/linspector.old.json @@ -0,0 +1,232 @@ +{ + "services": + { + "discusage": {"command": "ssh @host df -a @device", "parser": "df"}, + "load": {"command": "ssh @host uptime"}, + "dirsize": { "command": "ssh @host du -chs @path"}, + "filesize": {"command": "ssh @host du -chs @path"}, + "loggedinusercount": {"command": "ssh @host who | wc -l"}, + "loggedinusers": {"command": "ssh @host who"}, + "swapusage": {"command": "ssh @host cat /proc/swaps"}, + "processcount": {"command": "ssh @host ps ax | wc -l"}, + "processcountbyname": {"command": "ssh @host ps ax | grep @name | wc -l"}, + "fileage": {"command": "ssh @host ls -l @file"}, + "ping": {"command": "ping @host"}, + "snmpget": {"command": "snmpget -v1 -c public $oid"}, + "busy_waiting": {"command": "sleep 3600"}, + "htmlcontent": {"command": "wget -qO- @url", "comment": "Get HTML Content for a string lookup."} + }, + "filters": + { + "email": + { + "command": "/usr/bin/warn_the_admin_mail @member @+message", + "comment": "Sends an E-Mail to the member.", + "priority": 1 + }, + "sms": + { + "command": "/usr/bin/warn_the_admin_sms @member @+message", + "comment": "Sends a Short Message to the member.", + "priority": 0 + }, + "foo": + { + "command": "/usr/bin/warn_the_admin_foo @member @+message", + "priority": 500 + }, + "mongowriter": + { + "command": "./plugins/mongowriter.py @+message localhost 27017 linspector123", + "priority": 1000 + } + }, + "members": + { + "hanez": + { + "name": "Johannes Findeisen", + "comment": "Just a nerd doing admin stuff...", + "parent": "admin", + "filters": + { + "email": "you@hanez.org", + "sms": "+23345567" + } + }, + "linspector": + { + "name": "Linspector BOT", + "comment": "Botty Botsen...", + "parent": "admin", + "filters": + { + "email": "botty@hanez.org", + "sms": "+23345567213123" + } + }, + "unixpeople": + { + "name": "Hanna Findeisen", + "comment": "Master of UNIX", + "parent": "admin", + "filters": + { + "email": "master@hanez.org", + "sms": "+2334556733333" + } + }, + "admin": + { + "name": "Peter Hansen", + "comment": "The son of Hans-Peter Hansen", + "parent": "ultraadmin", + "filters": + { + "email": "admin@systemchaos.org", + "sms": "+23345567", + "phone": "+435345345" + } + }, + "ultraadmin": + { + "name": "Hans-Peter Hansen (CEO)", + "comment": "The guru of the Datacenter", + "parent": "darthvader", + "filters": + { + "email": "bofh@systemchaos.org", + "sms": "+23345567", + "phone": "+435345345" + } + }, + "darthvader": + { + "name": "Darth Vader", + "comment": "The Father", + "filters": + { + "email": "darth.vader@systemchaos.org" + } + }, + "jens": + { + "name": "Jens Larssen", + "comment": "Our network guru", + "filters": + { + "email": "jens@systemchaos.org", + "sms": "+23345567", + "phone": "+435345345" + } + }, + "ruff": + { + "name": "Ruffn Buffn", + "filters": + { + "sms": "+23343457" + } + }, + "mongowriter": + { + "name": "MongoDB Database writer plugin", + "filters": + { + "mongowriter": "localhost" + } + } + }, + "periods": + { + "twentyfourseven": + { + "year": "*", + "month": "*", + "day": "*", + "week": "*", + "hour": "*", + "minute": "*/1", + "second": "0", + "comment": "Cron Job / Every minute" + }, + "do_every_x_times" : { + "days": 0, + "weeks": 0, + "hours": 0, + "minutes": 0, + "seconds": 10, + "comment": "Interval Job / Every 10 seconds" + }, + "next_christmas" : { + "date": "2013-12-24 20:00:00", + "comment": "Date Job / Just one day" + } + }, + "hosts": + { + "hanez": + { + "host": "www.hanez.org", + "services": + { + "discusage": + [ + { "device": "/dev/sda1", "warning": "80%", "critical": "90%" }, + { "device": "/dev/sda2", "warning": "70%", "critical": "90%" }, + { "device": "/dev/sda3", "warning": "70GB", "critical": "90GB" } + ], + "load": + [ + { "warning": 8.00, "critical": 12.00 } + ], + "dirsize": + [ + { "path": "/var/log", "warning": 30000000, "critical": 40000000 } + ], + "processcount": + [ + { "warning": 3000, "critical": 3800 } + ], + "processcountbyname": + [ + { "name": "java", "warning": 100, "critical": 200 } + ], + "fileage": + [ + { "file": "/var/backup/server_1", "warning": 2, "critical": 3 } + ], + "htmlcontent": + [ + { "url": "@host/test.php", "content": "

Server up!

" } + ], + "ping": + [ + {} + ] + } + } + }, + "hostgroups": + { + "all": + { + "members": ["admin"], + "hosts": ["hanez"], + "parent": "network", + "threshold": 10, + "services": + { + "ping": ["do_every_x_times"] + } + } + }, + "layouts": {"production": {"hostgroups": ["all", "hanez", "network"], "enabled": true}, + "lazy": {"hostgroups": ["hanez", "ruff"], "enabled": false} + }, + "core": { + "max_logfile_size": 1024000, + "max_logfile_count": 4, + "max_worker_threads": 8 + } +} From 851069cc2aff3bd38667d35ca8e8ae4a9d8ce3a0 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 07:26:53 +0200 Subject: [PATCH 078/268] renamed filters to tasks... members.py needs some fixes now. think it is a good style to manage post processing. --- lib/__init__.py | 2 +- lib/config/config.py | 6 ++-- lib/config/filters.py | 17 --------- lib/config/tasks.py | 16 +++++++++ lib/filters/email.py | 3 -- lib/{filters => tasks}/__init__.py | 0 lib/tasks/email.py | 3 ++ linspector.json | 56 +++++++++++++++++------------- 8 files changed, 55 insertions(+), 48 deletions(-) delete mode 100644 lib/config/filters.py create mode 100644 lib/config/tasks.py delete mode 100644 lib/filters/email.py rename lib/{filters => tasks}/__init__.py (100%) create mode 100644 lib/tasks/email.py diff --git a/lib/__init__.py b/lib/__init__.py index c14c0bd..758045d 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,5 +1,5 @@ from config import * from core import * -from filters import * +from tasks import * from parser import * from service import * \ No newline at end of file diff --git a/lib/config/config.py b/lib/config/config.py index 4ad862f..dfb91dc 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -1,5 +1,5 @@ import json -from filters import parseFilterList +from tasks import parseTaskList from members import parseMemberList from periods import parsePeriodList #from hostgroups import parseHostGroupList @@ -15,8 +15,8 @@ class Config: self.dict = json.loads(self.config) - self.filters = parseFilterList(self.dict['filters']) - self.members = parseMemberList(self.dict['members'], self.filters, log) + self.tasks = parseTaskList(self.dict['tasks']) + self.members = parseMemberList(self.dict['members'], self.tasks, log) self.periods = parsePeriodList(self.dict['periods'], log) #self.hostgroups = parseHostGroupList(self.dict['hostgroups'], # self.members, diff --git a/lib/config/filters.py b/lib/config/filters.py deleted file mode 100644 index 06fa5a2..0000000 --- a/lib/config/filters.py +++ /dev/null @@ -1,17 +0,0 @@ -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()] \ No newline at end of file diff --git a/lib/config/tasks.py b/lib/config/tasks.py new file mode 100644 index 0000000..1907563 --- /dev/null +++ b/lib/config/tasks.py @@ -0,0 +1,16 @@ +class Task: + def __init__(self, name="", command="", priority=0, comment=""): + self.name = name + self.command = command + self.priority = priority + self.comment = comment + + def __str__(self): + return "Task('Name: " + self.name + "', 'Command: " + self.command + "', 'Priority: " + str(self.priority) + "')" + + def clone(self): + return Task(self.name, self.command, self.priority, self.comment) + + +def parseTaskList(tasks): + return [Task(name, **values) for name, values in tasks.items()] \ No newline at end of file diff --git a/lib/filters/email.py b/lib/filters/email.py deleted file mode 100644 index a625f1a..0000000 --- a/lib/filters/email.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -The email filter in pure Python. -""" \ No newline at end of file diff --git a/lib/filters/__init__.py b/lib/tasks/__init__.py similarity index 100% rename from lib/filters/__init__.py rename to lib/tasks/__init__.py diff --git a/lib/tasks/email.py b/lib/tasks/email.py new file mode 100644 index 0000000..d38e620 --- /dev/null +++ b/lib/tasks/email.py @@ -0,0 +1,3 @@ +""" +The email task. +""" \ No newline at end of file diff --git a/linspector.json b/linspector.json index 2031f78..2f1d877 100644 --- a/linspector.json +++ b/linspector.json @@ -1,42 +1,50 @@ { - "filters":{ + "tasks":{ "email":{ - "command":"email @member @+message", - "comment":"Sends an E-Mail to the member.", - "priority":1 + "command": "email @member @+message", + "comment": "Sends an E-Mail to a member.", + "priority": 2 + }, + "sms":{ + "command": "sms @member @+message", + "comment": "Sends a SMS to a member.", + "priority": 1 + }, + "mongodb":{ + "command": "mongodb @host @user @password @+rawdata", + "comment": "Stores the rawdata in a MongoDB database.", + "priority": 1000 } }, "members":{ "hanez":{ - "name":"Johannes Findeisen", - "comment":"Just a nerd doing admin stuff...", + "name": "Johannes Findeisen", + "comment": "Just a nerd doing admin stuff.", "parent": "darth", - "filters":{ "email":"you@hanez.org" } + "tasks":[{ "class": "email", "args": { "rcpt": "you@hanez.org" }}, + { "class": "sms","args": { "rcpt": "+49110"}}] }, "darth":{ - "name":"Darth Vader", - "comment":"The father", - "filters":{ "email":"darth.vader@hanez.org" } + "name": "Darth Vader", + "comment": "The father", + "tasks":{ "class": "email", "args": { "rcpt": "darth.vader@hanez.org" }} + }, + "mongodb":{ + "name": "MongoDB", + "comment": "The writer to a MongoDB", + "tasks":{ "class": "mongodb", "args": { "host": "localhost", "user": "root", "password": "root" }} } }, "periods":{ - "short":{ - "seconds":5, - "comment":"Interval job; every 10 seconds" - }, - "middle":{ - "seconds":60, - "comment":"Interval job; every 60 seconds" - }, - "long":{ - "minutes":2, - "comment":"Interval job; every 2 minutes" - } + "short":{ "seconds": 5, "comment": "Interval job; every 10 seconds" }, + "middle":{ "seconds": 60,"comment": "Interval job; every 60 seconds" }, + "long":{ "minutes": 2,"comment": "Interval job; every 2 minutes" }, + "christmas2013":{ "date": "2013-12-24 20:00:00", "comment": "Date Job; just one day at 8PM" } }, "hostgroups":{ "group1":{ - "members":[ "hanez" ], - "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], + "members": [ "hanez", "mongodb" ], + "hosts": [ "a.systemchaos.org", "b.systemchaos.org" ], "parents": [ "network" ], "services":[ { From ae9d400e18932eecf777c705d9b274a4c2a7ec03 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 5 Jun 2013 07:53:18 +0200 Subject: [PATCH 079/268] moved all old json files to examples/ and deleted old linspector exe. the json files are for historical evaluation and don't have to be in root anymore. --- linspector.old | 183 ------------------ .../linspector.full.json | 0 .../linspector.minimal.json | 0 .../linspector.old.json | 0 4 files changed, 183 deletions(-) delete mode 100755 linspector.old rename linspector.full.json => test/linspector.full.json (100%) rename linspector.minimal.json => test/linspector.minimal.json (100%) rename linspector.old.json => test/linspector.old.json (100%) diff --git a/linspector.old b/linspector.old deleted file mode 100755 index 1736a51..0000000 --- a/linspector.old +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/python2.7 -tt - -import sys -import time -import getopt -from lib.core.daemon import Daemon -from lib.config.config import Config -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() diff --git a/linspector.full.json b/test/linspector.full.json similarity index 100% rename from linspector.full.json rename to test/linspector.full.json diff --git a/linspector.minimal.json b/test/linspector.minimal.json similarity index 100% rename from linspector.minimal.json rename to test/linspector.minimal.json diff --git a/linspector.old.json b/test/linspector.old.json similarity index 100% rename from linspector.old.json rename to test/linspector.old.json From 6f7d7799a6fd3819205b36360dd35200e78e619c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 7 Jun 2013 02:20:27 +0200 Subject: [PATCH 080/268] some new ideas in linspector.json --- linspector.json | 51 ++++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/linspector.json b/linspector.json index 2f1d877..f7953a9 100644 --- a/linspector.json +++ b/linspector.json @@ -1,51 +1,41 @@ { - "tasks":{ - "email":{ - "command": "email @member @+message", - "comment": "Sends an E-Mail to a member.", - "priority": 2 - }, - "sms":{ - "command": "sms @member @+message", - "comment": "Sends a SMS to a member.", - "priority": 1 - }, - "mongodb":{ - "command": "mongodb @host @user @password @+rawdata", - "comment": "Stores the rawdata in a MongoDB database.", - "priority": 1000 - } - }, "members":{ + "root":{ + "name": "Admin", + "comment": "The Linspector Admin", + "tasks":[{ "class": "email", "args": { "rcpt": "admin@systems.hanez.org" }}, + { "class": "sms","args": { "rcpt": "+49112" }}] + }, "hanez":{ "name": "Johannes Findeisen", "comment": "Just a nerd doing admin stuff.", "parent": "darth", "tasks":[{ "class": "email", "args": { "rcpt": "you@hanez.org" }}, - { "class": "sms","args": { "rcpt": "+49110"}}] + { "class": "sms","args": { "rcpt": "+49110" }}] }, "darth":{ "name": "Darth Vader", "comment": "The father", "tasks":{ "class": "email", "args": { "rcpt": "darth.vader@hanez.org" }} - }, - "mongodb":{ - "name": "MongoDB", - "comment": "The writer to a MongoDB", - "tasks":{ "class": "mongodb", "args": { "host": "localhost", "user": "root", "password": "root" }} } }, "periods":{ "short":{ "seconds": 5, "comment": "Interval job; every 10 seconds" }, - "middle":{ "seconds": 60,"comment": "Interval job; every 60 seconds" }, - "long":{ "minutes": 2,"comment": "Interval job; every 2 minutes" }, + "middle":{ "seconds": 60, "comment": "Interval job; every 60 seconds" }, + "long":{ "minutes": 2, "comment": "Interval job; every 2 minutes" }, "christmas2013":{ "date": "2013-12-24 20:00:00", "comment": "Date Job; just one day at 8PM" } }, "hostgroups":{ "group1":{ - "members": [ "hanez", "mongodb" ], - "hosts": [ "a.systemchaos.org", "b.systemchaos.org" ], - "parents": [ "network" ], + "members":[ "hanez", "mongodb" ], + "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], + "parents":[ "network" ], + "processors":[ + { + "class": "mongodb", + "args": { "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} + } + ], "services":[ { "class":"ping", @@ -140,13 +130,14 @@ "enabled": false }, "all":{ - "hostgroups": [ "group1", "group2", "group3" ], + "hostgroups": [ "group1", "group2", "group3", "network" ], "enabled": false } }, "core":{ "max_logfile_size": 1024000, "max_logfile_count": 4, - "max_worker_threads": 8 + "max_worker_threads": 8, + "members": [ "root" ] } } From e4d3f98ad7c3e4a36700356ede706d520531ce00 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 9 Jun 2013 23:25:42 +0200 Subject: [PATCH 081/268] added nbproject to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 590d78f..1c99887 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea .project .pydevproject +nbproject *.py[cod] From 9b28951975a18f113cfcb92748e1ae545c45d9cb Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Mon, 10 Jun 2013 00:31:39 +0200 Subject: [PATCH 082/268] added cronjob, changed service.py a little --- lib/service/service.py | 14 +++++++------- linspector.json | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/service/service.py b/lib/service/service.py index 89f02a2..a2f15a4 100644 --- a/lib/service/service.py +++ b/lib/service/service.py @@ -7,9 +7,9 @@ class Service: def _execute(self): self.pre_execute() - self.execute() - self.parse_result() - self.handle_result() + executionResult = self.execute() + parseResult = self.parse_result(executionResult) + self.handle_result(parseResult) def execute(self): pass @@ -17,8 +17,8 @@ class Service: def pre_execute(self): pass - def parse_result(self): - self.parser._parse() + def parse_result(self, executionResult): + return self.parser._parse(executionResult) - def handle_result(self): - pass \ No newline at end of file + def handle_result(self, parseResult): + pass diff --git a/linspector.json b/linspector.json index f7953a9..2255293 100644 --- a/linspector.json +++ b/linspector.json @@ -23,6 +23,7 @@ "short":{ "seconds": 5, "comment": "Interval job; every 10 seconds" }, "middle":{ "seconds": 60, "comment": "Interval job; every 60 seconds" }, "long":{ "minutes": 2, "comment": "Interval job; every 2 minutes" }, + "cron":{ "minute" : "0", "hour": "2", "comment": "cron job at 2"}, "christmas2013":{ "date": "2013-12-24 20:00:00", "comment": "Date Job; just one day at 8PM" } }, "hostgroups":{ From 8b700e8915b39fe6b05c8f87258e6e1a1c402c22 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 01:06:28 +0200 Subject: [PATCH 083/268] added type to tasks for handling warning and critical alerts differently --- linspector.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/linspector.json b/linspector.json index 2255293..62ab0ce 100644 --- a/linspector.json +++ b/linspector.json @@ -3,20 +3,20 @@ "root":{ "name": "Admin", "comment": "The Linspector Admin", - "tasks":[{ "class": "email", "args": { "rcpt": "admin@systems.hanez.org" }}, - { "class": "sms","args": { "rcpt": "+49112" }}] + "tasks":[{ "class": "email", "type": "warning", "args": { "rcpt": "admin@systems.hanez.org" }}, + { "class": "sms", "type": "critical", "args": { "rcpt": "+49112" }}] }, "hanez":{ "name": "Johannes Findeisen", "comment": "Just a nerd doing admin stuff.", "parent": "darth", - "tasks":[{ "class": "email", "args": { "rcpt": "you@hanez.org" }}, - { "class": "sms","args": { "rcpt": "+49110" }}] + "tasks":[{ "class": "email", "type": "warning", "args": { "rcpt": "you@hanez.org" }}, + { "class": "sms", "type": "critical", "args": { "rcpt": "+49110" }}] }, "darth":{ "name": "Darth Vader", "comment": "The father", - "tasks":{ "class": "email", "args": { "rcpt": "darth.vader@hanez.org" }} + "tasks":{ "class": "email", "type": "warning", "args": { "rcpt": "darth.vader@hanez.org" }} } }, "periods":{ From b74970a13cddd8ff9662fb043331ec3ffc5f8106 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 03:35:57 +0200 Subject: [PATCH 084/268] added some snmpget services and some small new features in the config... ;) --- linspector.json | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/linspector.json b/linspector.json index 62ab0ce..c9b62cc 100644 --- a/linspector.json +++ b/linspector.json @@ -110,13 +110,36 @@ "network":{ "members":[ "hanez" ], "hosts":[ "router.systemchaos.org" ], + "processors":[ + { + "class": "mongodb", + "args": { "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} + } + ], "services":[ { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, + "class": "shell", + "comment": "ping using the shell service and no builtin", + "args": { "command": "ping -c4 @host" }, + "fails":{ "warning": "100ms", "critical":"150ms", "notes": "HeyHo! A ping failed, wake up! (@response)" }, "periods": ["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } + "threshold": 10, + "parser":{ "class": "shell", "line": 2, "col": 5 } + }, + { + "class":"snmpget", + "comment": "The system load", + "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, + "fails":{ "warning":"4.00", "critical":"8.00" }, + "periods": ["middle"], + "threshold": 10 + }, + { + "class":"snmpget", + "comment": "The system uptime", + "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.2.1.1.3.0" }, + "periods": ["middle"], + "threshold": 10 } ] } From 0e6634a0259a1c6c5d6d2ad19db87e4dafe0f3e5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:04:48 +0200 Subject: [PATCH 085/268] added some task stuff --- lib/tasks/sms.py | 3 +++ lib/tasks/xmpp.py | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 lib/tasks/sms.py create mode 100644 lib/tasks/xmpp.py diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py new file mode 100644 index 0000000..41f2d0c --- /dev/null +++ b/lib/tasks/sms.py @@ -0,0 +1,3 @@ +""" +The sms task. +""" \ No newline at end of file diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py new file mode 100644 index 0000000..2bb064c --- /dev/null +++ b/lib/tasks/xmpp.py @@ -0,0 +1,3 @@ +""" +The xmpp task. +""" \ No newline at end of file From 327e2e9ab24805a61a0f018f3750649919c7fd18 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:06:38 +0200 Subject: [PATCH 086/268] renamed parser/ to parsers/ --- lib/{parser => parsers}/__init__.py | 0 lib/{parser => parsers}/parser.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename lib/{parser => parsers}/__init__.py (100%) rename lib/{parser => parsers}/parser.py (100%) diff --git a/lib/parser/__init__.py b/lib/parsers/__init__.py similarity index 100% rename from lib/parser/__init__.py rename to lib/parsers/__init__.py diff --git a/lib/parser/parser.py b/lib/parsers/parser.py similarity index 100% rename from lib/parser/parser.py rename to lib/parsers/parser.py From d09b08520ab8e4c397f16d672948ef85245759ae Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:10:47 +0200 Subject: [PATCH 087/268] added processors/ and the mongodb dummy --- lib/__init__.py | 5 +++-- lib/processors/__init__.py | 0 lib/processors/mongodb.py | 3 +++ 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 lib/processors/__init__.py create mode 100644 lib/processors/mongodb.py diff --git a/lib/__init__.py b/lib/__init__.py index 758045d..7301f66 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,5 +1,6 @@ from config import * from core import * from tasks import * -from parser import * -from service import * \ No newline at end of file +from parsers import * +from processors import * +from services import * \ No newline at end of file diff --git a/lib/processors/__init__.py b/lib/processors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py new file mode 100644 index 0000000..28b5c85 --- /dev/null +++ b/lib/processors/mongodb.py @@ -0,0 +1,3 @@ +""" +The MongoDB processor +""" \ No newline at end of file From d48c7957f8dfbb5964cfda3aaafc5ca62f2c95ac Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:14:02 +0200 Subject: [PATCH 088/268] added some more snmp stuff using the shell service for executing the snmpget command using no builtin; cleanups... --- linspector.json | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/linspector.json b/linspector.json index c9b62cc..46ef879 100644 --- a/linspector.json +++ b/linspector.json @@ -4,7 +4,8 @@ "name": "Admin", "comment": "The Linspector Admin", "tasks":[{ "class": "email", "type": "warning", "args": { "rcpt": "admin@systems.hanez.org" }}, - { "class": "sms", "type": "critical", "args": { "rcpt": "+49112" }}] + { "class": "sms", "type": "critical", "args": { "rcpt": "+49112" }}, + { "class": "xmpp", "type": "critical", "args": { "rcpt": "admin@jabber.hanez.org" }}] }, "hanez":{ "name": "Johannes Findeisen", @@ -28,7 +29,7 @@ }, "hostgroups":{ "group1":{ - "members":[ "hanez", "mongodb" ], + "members":[ "hanez" ], "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], "parents":[ "network" ], "processors":[ @@ -104,6 +105,15 @@ "threshold":10, "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, [{ "class":"grep", "line": "/dev/sda2", "col":5 }, { "class":"grep", "line": "/dev/sda2", "col":5 }]] + }, + { + "class": "shell", + "comment": "Getting the Linux system load using the shell service and the snmpget command", + "args":{ "command": "snmpget -v2c -c linspector @host .1.3.6.1.4.1.2021.10.1.3.1" }, + "fails":{ "warning": "4.00", "critical":"8.00" }, + "periods":[ "middle" ], + "threshold": 10, + "parser":{ "class": "shell", "line": 1, "col": 4 } } ] }, @@ -113,32 +123,32 @@ "processors":[ { "class": "mongodb", - "args": { "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} + "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} } ], "services":[ { "class": "shell", "comment": "ping using the shell service and no builtin", - "args": { "command": "ping -c4 @host" }, + "args":{ "command": "ping -c1 @host" }, "fails":{ "warning": "100ms", "critical":"150ms", "notes": "HeyHo! A ping failed, wake up! (@response)" }, - "periods": ["short"], + "periods":[ "short" ], "threshold": 10, - "parser":{ "class": "shell", "line": 2, "col": 5 } + "parser":{ "class": "shell", "line": 2, "col": 8 } }, { - "class":"snmpget", - "comment": "The system load", + "class": "snmpget", + "comment": "The Linux system load", "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, "fails":{ "warning":"4.00", "critical":"8.00" }, - "periods": ["middle"], + "periods":[ "middle" ], "threshold": 10 }, { - "class":"snmpget", - "comment": "The system uptime", + "class": "snmpget", + "comment": "The Linux system uptime", "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.2.1.1.3.0" }, - "periods": ["middle"], + "periods":[ "middle" ], "threshold": 10 } ] From 4b0238c5150b0bd9155abfcb9ea601169f7af6c3 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:14:53 +0200 Subject: [PATCH 089/268] added some testing code to the snmpget builtin and renamed service to services/ --- lib/{service => services}/__init__.py | 0 lib/{service => services}/http.py | 0 lib/{service => services}/ping.py | 0 lib/{service => services}/service.py | 0 lib/{service => services}/shell.py | 0 lib/services/snmpget.py | 58 +++++++++++++++++++++++++ lib/{service => services}/ssh.py | 0 lib/{service => services}/tcpconnect.py | 0 8 files changed, 58 insertions(+) rename lib/{service => services}/__init__.py (100%) rename lib/{service => services}/http.py (100%) rename lib/{service => services}/ping.py (100%) rename lib/{service => services}/service.py (100%) rename lib/{service => services}/shell.py (100%) create mode 100644 lib/services/snmpget.py rename lib/{service => services}/ssh.py (100%) rename lib/{service => services}/tcpconnect.py (100%) diff --git a/lib/service/__init__.py b/lib/services/__init__.py similarity index 100% rename from lib/service/__init__.py rename to lib/services/__init__.py diff --git a/lib/service/http.py b/lib/services/http.py similarity index 100% rename from lib/service/http.py rename to lib/services/http.py diff --git a/lib/service/ping.py b/lib/services/ping.py similarity index 100% rename from lib/service/ping.py rename to lib/services/ping.py diff --git a/lib/service/service.py b/lib/services/service.py similarity index 100% rename from lib/service/service.py rename to lib/services/service.py diff --git a/lib/service/shell.py b/lib/services/shell.py similarity index 100% rename from lib/service/shell.py rename to lib/services/shell.py diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py new file mode 100644 index 0000000..4eb974d --- /dev/null +++ b/lib/services/snmpget.py @@ -0,0 +1,58 @@ +""" +The snmpget service in pure Python. +""" + +# http://pysnmp.sourceforge.net/ + +""" +1. install net-snmp package on localhost +2. Use this /etc/snmp/snmpd.conf: + +com2sec local 127.0.0.1/32 linspector +com2sec local 192.168.2.0/24 linspector +# +group MyROGroup v1 local +group MyROGroup v2c local +group MyROGroup usm local +view all included .1 80 +access MyROGroup "" any noauth exact all none none +# +syslocation Sylt +syscontact Admin {Admin@example.com} +3. start the snmpd service +4. the following code should work +""" + +from pysnmp.entity.rfc3413.oneliner import cmdgen + +cmdGen = cmdgen.CommandGenerator() + +errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( + cmdgen.CommunityData('linspector'), + cmdgen.UdpTransportTarget(('localhost', 161)), + + # Names variables: + #cmdgen.MibVariable('SNMPv2-MIB', 'sysName', 0) + + # OID's: + cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.1') # load + #cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.2') # load + #cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.3') # load + #cmdgen.MibVariable('.1.3.6.1.2.1.1.3.0') # systems uptime + # more: + # http://www.debianadmin.com/linux-snmp-oids-for-cpumemory-and-disk-statistics.html + # http://www.mibdepot.com/index.shtml +) + +# Check for errors and print out results +if errorIndication: + print(errorIndication) +else: + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex) - 1] or '?' + )) + else: + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) \ No newline at end of file diff --git a/lib/service/ssh.py b/lib/services/ssh.py similarity index 100% rename from lib/service/ssh.py rename to lib/services/ssh.py diff --git a/lib/service/tcpconnect.py b/lib/services/tcpconnect.py similarity index 100% rename from lib/service/tcpconnect.py rename to lib/services/tcpconnect.py From 3fc190025e66a9a86e6643c21d52fbcaf9f6aca8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 04:42:26 +0200 Subject: [PATCH 090/268] whitespacing... uuuh, the json file looks sexy now... ;) --- linspector.json | 103 ++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/linspector.json b/linspector.json index 46ef879..97b2850 100644 --- a/linspector.json +++ b/linspector.json @@ -3,28 +3,28 @@ "root":{ "name": "Admin", "comment": "The Linspector Admin", - "tasks":[{ "class": "email", "type": "warning", "args": { "rcpt": "admin@systems.hanez.org" }}, - { "class": "sms", "type": "critical", "args": { "rcpt": "+49112" }}, - { "class": "xmpp", "type": "critical", "args": { "rcpt": "admin@jabber.hanez.org" }}] + "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, + { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, + { "class": "xmpp", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] }, "hanez":{ "name": "Johannes Findeisen", "comment": "Just a nerd doing admin stuff.", "parent": "darth", - "tasks":[{ "class": "email", "type": "warning", "args": { "rcpt": "you@hanez.org" }}, - { "class": "sms", "type": "critical", "args": { "rcpt": "+49110" }}] + "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "you@hanez.org" }}, + { "class": "sms", "type": "critical", "args":{ "rcpt": "+49110" }}] }, "darth":{ "name": "Darth Vader", "comment": "The father", - "tasks":{ "class": "email", "type": "warning", "args": { "rcpt": "darth.vader@hanez.org" }} + "tasks":{ "class": "email", "type": "warning", "args":{ "rcpt": "darth.vader@hanez.org" }} } }, "periods":{ "short":{ "seconds": 5, "comment": "Interval job; every 10 seconds" }, "middle":{ "seconds": 60, "comment": "Interval job; every 60 seconds" }, "long":{ "minutes": 2, "comment": "Interval job; every 2 minutes" }, - "cron":{ "minute" : "0", "hour": "2", "comment": "cron job at 2"}, + "cron":{ "minute" : "0", "hour": "2", "comment": "Cron job; at 2 o'clock" }, "christmas2013":{ "date": "2013-12-24 20:00:00", "comment": "Date Job; just one day at 8PM" } }, "hostgroups":{ @@ -35,61 +35,61 @@ "processors":[ { "class": "mongodb", - "args": { "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} + "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default" } } ], "services":[ { - "class":"ping", + "class": "ping", "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods": ["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } + "periods":[ "short" ], + "threshold": 10, + "parser":{ "class": "shell", "line": 2, "col": 5 } }, { - "class":"tcpconnect", - "args":{ "port":80 }, - "periods": ["middle"], - "threshold":2 + "class": "tcpconnect", + "args":{ "port": 80 }, + "periods":[ "middle" ], + "threshold": 2 }, { - "class":"tcpconnect", - "args":{ "port":25 }, - "periods":["long"], - "threshold":2 + "class": "tcpconnect", + "args":{ "port": 25 }, + "periods":["long" ], + "threshold": 2 }, { - "class":"tcpconnect", - "args":{ "port":110 }, - "periods": ["long"], - "threshold":2 + "class": "tcpconnect", + "args":{ "port": 110 }, + "periods":[ "long" ], + "threshold": 2 }, { - "class":"http", - "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params": { "foo": 1, "bar": 2 }, "protocol": "https"}, - "periods": ["long"], - "threshold":2, + "class": "http", + "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params":{ "foo": 1, "bar": 2 }, "protocol": "https" }, + "periods":[ "long" ], + "threshold": 2, "parser":{ "class":"grep", "string": "

I am up!

" }, "comment": "Just a string grep" } ] }, "group2":{ - "members":["hanez"], - "hosts":["x.systemchaos.org", "y.systemchaos.org"], + "members":["hanez" ], + "hosts":["x.systemchaos.org", "y.systemchaos.org" ], "services":[ { - "class":"ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, - "periods":["short"], - "threshold":10, - "parser":{ "class":"shell", "line":2, "col":5 } + "class": "ping", + "fails":{ "warning": "100ms", "critical": "150ms" }, + "periods":[ "short" ], + "threshold": 10, + "parser":{ "class": "shell", "line": 2, "col": 5 } }, { - "class":"tcpconnect", - "args":{ "port":2342 }, - "periods":["long"], - "threshold":2 + "class": "tcpconnect", + "args":{ "port": 2342 }, + "periods":[ "long" ], + "threshold": 2 } ] }, @@ -98,13 +98,14 @@ "hosts":[ "master.systemchaos.org" ], "services":[ { - "class":"ssh", + "class": "ssh", "args":{ "port": 23, "command": "df", "username": "hanez", "password": "secret", "key": "~/.ssh/id_rsa" }, - "fails":{ "warning":"80%", "critical":"90%" }, + "fails":{ "warning": "80%", "critical": "90%" }, "periods":[ "long" ], - "threshold":10, - "parser": [{ "class":"grep", "line": "/dev/sda1", "col":5 }, - [{ "class":"grep", "line": "/dev/sda2", "col":5 }, { "class":"grep", "line": "/dev/sda2", "col":5 }]] + "threshold": 10, + "parser":[{ "class":"grep", "line": "/dev/sda1", "col": 5 }, + [{ "class":"grep", "line": "/dev/sda2", "col": 5 }, + { "class":"grep", "line": "/dev/sda2", "col": 5 }]] }, { "class": "shell", @@ -123,7 +124,7 @@ "processors":[ { "class": "mongodb", - "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default"} + "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default" } } ], "services":[ @@ -140,7 +141,7 @@ "class": "snmpget", "comment": "The Linux system load", "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, - "fails":{ "warning":"4.00", "critical":"8.00" }, + "fails":{ "warning": "4.00", "critical": "8.00" }, "periods":[ "middle" ], "threshold": 10 }, @@ -156,15 +157,15 @@ }, "layouts":{ "production":{ - "hostgroups": [ "group1" ], + "hostgroups":[ "group1" ], "enabled": true }, "critical":{ - "hostgroups": [ "group3" ], + "hostgroups":[ "group3" ], "enabled": false }, "all":{ - "hostgroups": [ "group1", "group2", "group3", "network" ], + "hostgroups":[ "group1", "group2", "group3", "network" ], "enabled": false } }, @@ -172,6 +173,6 @@ "max_logfile_size": 1024000, "max_logfile_count": 4, "max_worker_threads": 8, - "members": [ "root" ] + "members":[ "root" ] } -} +} \ No newline at end of file From 7f45a148021ca062d85373437ef6ade3e19890c7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 05:01:40 +0200 Subject: [PATCH 091/268] converted snmpget service to generic linspector service; raising exceptions from all services now when needed args are missing. --- lib/services/http.py | 1 + lib/services/shell.py | 1 + lib/services/snmpget.py | 86 +++++++++++++++++--------------------- lib/services/ssh.py | 1 + lib/services/tcpconnect.py | 1 + 5 files changed, 42 insertions(+), 48 deletions(-) diff --git a/lib/services/http.py b/lib/services/http.py index f967ad4..706d419 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -20,6 +20,7 @@ class HttpService(Service): self.string = kwargs["string"] else: log.w("There is no string set to match") + raise if "method" in kwargs: self.method = kwargs["method"] diff --git a/lib/services/shell.py b/lib/services/shell.py index 097ac35..7b5c78c 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -12,6 +12,7 @@ class ShellService(Service): self.command = kwargs["command"] else: log.w("There is no command") + raise def execute(self): self.command.call() \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index 4eb974d..68652e6 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -2,57 +2,47 @@ The snmpget service in pure Python. """ -# http://pysnmp.sourceforge.net/ - -""" -1. install net-snmp package on localhost -2. Use this /etc/snmp/snmpd.conf: - -com2sec local 127.0.0.1/32 linspector -com2sec local 192.168.2.0/24 linspector -# -group MyROGroup v1 local -group MyROGroup v2c local -group MyROGroup usm local -view all included .1 80 -access MyROGroup "" any noauth exact all none none -# -syslocation Sylt -syscontact Admin {Admin@example.com} -3. start the snmpd service -4. the following code should work -""" - from pysnmp.entity.rfc3413.oneliner import cmdgen +from service import Service -cmdGen = cmdgen.CommandGenerator() -errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( - cmdgen.CommunityData('linspector'), - cmdgen.UdpTransportTarget(('localhost', 161)), +class SnmpgetService(Service): + def __init__(self, **kwargs): - # Names variables: - #cmdgen.MibVariable('SNMPv2-MIB', 'sysName', 0) + if "community" in kwargs: + self.community = kwargs["community"] + else: + #log.w("There is no community") + raise - # OID's: - cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.1') # load - #cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.2') # load - #cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.3') # load - #cmdgen.MibVariable('.1.3.6.1.2.1.1.3.0') # systems uptime - # more: - # http://www.debianadmin.com/linux-snmp-oids-for-cpumemory-and-disk-statistics.html - # http://www.mibdepot.com/index.shtml -) + if "oid" in kwargs: + self.oid = kwargs["oid"] + else: + #log.w("There is no oid") + raise -# Check for errors and print out results -if errorIndication: - print(errorIndication) -else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex) - 1] or '?' - )) - else: - for name, val in varBinds: - print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) \ No newline at end of file + if "port" in kwargs: + self.port = kwargs["port"] + else: + self.port = "161" + + def execute(self): + cmdGen = cmdgen.CommandGenerator() + + errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( + cmdgen.CommunityData(self.community), + cmdgen.UdpTransportTarget((self.host, self.port)), + cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.1') # linux system load + ) + + if errorIndication: + print(errorIndication) + else: + if errorStatus: + print('%s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBinds[int(errorIndex) - 1] or '?' + )) + else: + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) \ No newline at end of file diff --git a/lib/services/ssh.py b/lib/services/ssh.py index 7b94c02..3131571 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -17,6 +17,7 @@ class SshService(Service): self.command = kwargs["command"] else: log.w("There is no command") + raise def execute(self): path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 2306b4b..b81bc7e 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -17,6 +17,7 @@ class TcpconnectService(Service): self.port = kwargs["port"] else: log.w("There is no port set") + raise def execute(self, log): try: From 226dfdce6e1d82ceb49bc5fe4e7abc08f2c4dbec Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 05:08:22 +0200 Subject: [PATCH 092/268] wthat the hack is an oid.... :)))) --- lib/services/snmpget.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index 68652e6..38357d6 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -32,7 +32,7 @@ class SnmpgetService(Service): errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( cmdgen.CommunityData(self.community), cmdgen.UdpTransportTarget((self.host, self.port)), - cmdgen.MibVariable('.1.3.6.1.4.1.2021.10.1.3.1') # linux system load + cmdgen.MibVariable(self.oid) ) if errorIndication: From f9b2f2e0edb41e792c6727fac498b439953d88c5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 05:20:50 +0200 Subject: [PATCH 093/268] who needs newlines...? --- lib/services/http.py | 6 ------ lib/services/snmpget.py | 10 ++++------ lib/services/tcpconnect.py | 1 - 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib/services/http.py b/lib/services/http.py index 706d419..224f1a8 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -15,31 +15,25 @@ from service import Service class HttpService(Service): def __init__(self, parser, log, **kwargs): super(Service, self).__init__(parser) - if "string" in kwargs: self.string = kwargs["string"] else: log.w("There is no string set to match") raise - if "method" in kwargs: self.method = kwargs["method"] else: self.method = "get" - if "params" in kwargs: self.params = kwargs["params"] - if "path" in kwargs: self.path = kwargs["path"] else: self.path = "/" - if "port" in kwargs: self.port = kwargs["port"] else: self.port = "80" - if "protocol" in kwargs: self.protocol = kwargs["protocol"] else: diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index 38357d6..fde9f9d 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -7,20 +7,18 @@ from service import Service class SnmpgetService(Service): - def __init__(self, **kwargs): - + def __init__(self, parser, log, **kwargs): + super(Service, self).__init__(parser) if "community" in kwargs: self.community = kwargs["community"] else: - #log.w("There is no community") + log.w("There is no community") raise - if "oid" in kwargs: self.oid = kwargs["oid"] else: - #log.w("There is no oid") + log.w("There is no oid") raise - if "port" in kwargs: self.port = kwargs["port"] else: diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index b81bc7e..43b043c 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -12,7 +12,6 @@ from service import Service class TcpconnectService(Service): def __init__(self, parser, log, **kwargs): super(Service, self).__init__(parser) - if "port" in kwargs: self.port = kwargs["port"] else: From bfcb6cee3256483d5287f1b46a531192dd971d95 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 10 Jun 2013 06:52:45 +0200 Subject: [PATCH 094/268] sexy, sexy, sexy... --- linspector.json | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/linspector.json b/linspector.json index 97b2850..3824198 100644 --- a/linspector.json +++ b/linspector.json @@ -41,7 +41,7 @@ "services":[ { "class": "ping", - "fails":{ "warning":"100ms", "critical":"150ms" }, + "fails":{ "warning": "100ms", "critical": "150ms" }, "periods":[ "short" ], "threshold": 10, "parser":{ "class": "shell", "line": 2, "col": 5 } @@ -55,7 +55,7 @@ { "class": "tcpconnect", "args":{ "port": 25 }, - "periods":["long" ], + "periods":[ "long" ], "threshold": 2 }, { @@ -66,16 +66,18 @@ }, { "class": "http", - "args":{ "port": 80, "path": "/status.cgi", "method": "get", "params":{ "foo": 1, "bar": 2 }, "protocol": "https" }, + "args":{ "port": 80, "path": "/status.cgi", "method": "get", + "params":{ "action": "go", "value": 1 }, + "protocol": "https" }, "periods":[ "long" ], "threshold": 2, - "parser":{ "class":"grep", "string": "

I am up!

" }, + "parser":{ "class": "grep", "string": "

I am up!

" }, "comment": "Just a string grep" } ] }, "group2":{ - "members":["hanez" ], + "members":[ "hanez" ], "hosts":["x.systemchaos.org", "y.systemchaos.org" ], "services":[ { @@ -103,15 +105,15 @@ "fails":{ "warning": "80%", "critical": "90%" }, "periods":[ "long" ], "threshold": 10, - "parser":[{ "class":"grep", "line": "/dev/sda1", "col": 5 }, - [{ "class":"grep", "line": "/dev/sda2", "col": 5 }, - { "class":"grep", "line": "/dev/sda2", "col": 5 }]] + "parser":[{ "class": "grep", "line": "/dev/sda1", "col": 5 }, + [{ "class": "grep", "line": "/dev/sda2", "col": 5 }, + { "class": "grep", "line": "/dev/sda2", "col": 5 }]] }, { "class": "shell", "comment": "Getting the Linux system load using the shell service and the snmpget command", "args":{ "command": "snmpget -v2c -c linspector @host .1.3.6.1.4.1.2021.10.1.3.1" }, - "fails":{ "warning": "4.00", "critical":"8.00" }, + "fails":{ "warning": 4.00, "critical": 8.00 }, "periods":[ "middle" ], "threshold": 10, "parser":{ "class": "shell", "line": 1, "col": 4 } @@ -132,7 +134,7 @@ "class": "shell", "comment": "ping using the shell service and no builtin", "args":{ "command": "ping -c1 @host" }, - "fails":{ "warning": "100ms", "critical":"150ms", "notes": "HeyHo! A ping failed, wake up! (@response)" }, + "fails":{ "warning": "100ms", "critical": "150ms", "notes": "HeyHo! A ping failed, wake up! (@response)" }, "periods":[ "short" ], "threshold": 10, "parser":{ "class": "shell", "line": 2, "col": 8 } @@ -141,13 +143,13 @@ "class": "snmpget", "comment": "The Linux system load", "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, - "fails":{ "warning": "4.00", "critical": "8.00" }, + "fails":{ "warning": 4.00, "critical": 8.00 }, "periods":[ "middle" ], "threshold": 10 }, { "class": "snmpget", - "comment": "The Linux system uptime", + "comment": "The Linux system uptime just processed... not more.", "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.2.1.1.3.0" }, "periods":[ "middle" ], "threshold": 10 From 89b637e851cdbb568f02d33c0c1f2f490dec8b15 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 11 Jun 2013 01:21:18 +0200 Subject: [PATCH 095/268] added new parser for config --- lib/config/hostgroups.py | 40 ++++++++-- lib/config/layouts.py | 29 +++++++- lib/config/parser.py | 153 +++++++++++++++++++++++++++++++++++++++ linspector | 16 +--- 4 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 lib/config/parser.py diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 87d03cb..6614a91 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -1,13 +1,37 @@ +class HostGroupException(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + +class HostGroupMissingArgumentException(HostGroupException): + def __init__(self, missingArgument, hostgroupName): + super(HostGroupMissingArgumentException, self).__init__("no " + missingArgument + " defined for Hostgroup " + hostgroupName) + class HostGroup: - def __init__(self, name, members="", hosts="", services="", threshold="", parent="", comment=""): + def __init__(self, name, **kwargs): self.name = name - self.interval = 0 - self.members = members - self.hosts = hosts - self.services = services - self.threshold = threshold - self.parent = parent - self.comment = comment + + tmp = "members" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.members = kwargs[tmp] + + tmp = "hosts" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.hosts = kwargs[tmp] + + tmp = "services" + if not tmp in kwargs: + raise HostGroupMissingArgumentException(tmp, name) + self.services = kwargs[tmp] + + + def get_members(self): + return self.members + def __str__(self): ret = "HostGroup: " + self.name + " threshold: " + str(self.threshold) + " parent: " + self.parent + "\n" diff --git a/lib/config/layouts.py b/lib/config/layouts.py index d8a6822..df47d30 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -1,8 +1,28 @@ +class LayouException(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return repr(self.msg) + class Layout: - def __init__(self, myLayout): - self.name = myLayout - self.enabled = False - self.hostgroups = [] + def __init__(self, name, enabled = False , hostgroups=None): + self._name = name + self._enabled = enabled + + if hostgroups is None or len(hostgroups) <= 0: + raise Exception("Layout: " + name + " without hostgroups is useless") + else: + self._hostgroups = hostgroups + + def get_name(self): + return self._name + + def is_enabled(self): + return self._enabled + + def get_hostgroups(self): + return self._hostgroups def __str__(self): ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " " @@ -38,6 +58,7 @@ class LayoutList: else: # TODO: replace next line with new logging #logger.logWarningConfig(file="hostgroups", missing=group) + pass self.layouts.append(l) def __str__(self): diff --git a/lib/config/parser.py b/lib/config/parser.py new file mode 100644 index 0000000..72e893f --- /dev/null +++ b/lib/config/parser.py @@ -0,0 +1,153 @@ +''' +Created on Jun 9, 2013 + +@author: Rafael Timmerberg(raffn1+linspector@gmail.com) +''' + +import os, os.path as path +import json +from layouts import Layout +from hostgroups import HostGroup + +class ConfigurationException(Exception): + def __init__(self, msg, log): + log.e(msg) + self.msg = msg + + def __str__(self): + return repr(self.msg) + + +KEY_LAYOUTS = "layouts" +KEY_HOSTGROUPS = "hostgroups" +KEY_MEMBERS = "members" +KEY_PERIODS = "periods" +KEY_CORE = "core" + + + +class ConfigParser: + def __init__(self, log): + ''' + initializes a new ConfigParser Object + + params: + log: pre configured logger Object to post messages while parsing" + ''' + self.log = log + self.hostgroups = {} + self.members = {} + self.periods = {} + + + def _read_json_config(self, configFilename): + ''' + reads the config File and returns a dictionary, while lowering the first keys + + params: + configFilename: the path under which the configuration file should be found + ''' + if not path.isfile(configFilename): + msg = "config file not found at " + str(configFilename) + raise ConfigurationException(msg, self.log) + + self.configfilename = configFilename + + with open(configFilename) as cfgFile: + config = cfgFile.read() + + self.log.i("reading Config: " + configFilename) + return json.loads(config) + + + + def _get_as_list(self, configValue): + ''' + In some cases the config permits to define a list or a single value. + + returns the value as list + ''' + return configValue if isinstance(configValue, list) else [configValue] + + + def create_layouts_from_json(self, jsonLayouts): + layouts = [] + for lName, lValues in jsonLayouts.items(): + try: + layout = Layout(lName, **lValues) + layouts.append(layout) + except Exception: + self.log.w("ignoring Layout " + lName + "! reason:") + self.log.w(str(Exception)) + return layouts + + + def create_hostgroups_from_json(self, jsonHostGroups): + ''' + creates Hostgroups from the jsonConfig + ''' + hostgroups = [] + for hgName, hgValues in jsonHostGroups.items(): + try: + hostgroup = HostGroup(hgName, **hgValues) + hostgroups.append(hostgroup) + except Exception: + self.log.w("ignoring hostgroup: " + hgName + "!") + self.log.w("reason: " + str(Exception)) + return hostgroups + + + + + def parse_config(self, configFilename): + ''' + parses the json configuration and returns a list of layouts, + which contains all nessesary information of the config file. + Parsing will be done in 3 steps: + 1. get raw Config Objects by just passing the values defined inside the config + 2. replace references by objects + 3. do sanity checks + + params: + configFilename: indicates which configuration file to parse + ''' + + self.jsonDict = self._read_json_config(configFilename) + + jsonLayouts = self.jsonDict[KEY_LAYOUTS] + layouts = self.create_layouts_from_json(jsonLayouts) + + hostgroupNames = set() + for layout in layouts: + for hgName in layout.get_hostgroups(): + hostgroupNames.add(hgName) + + + jsonHostgroups = {} + for hgName in hostgroupNames: + if not hgName in self.jsonDict[KEY_HOSTGROUPS]: + self.log.w("Hostgroup " + hgName + " not found!") + for layout in layouts: + if hgName in layout.hostgroups: + del layout.hostgroups[layout.hostgroups.index(hgName)] + jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] + + self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) + + memberNames = set() + for hostgroup in self.hostgroups: + for memberName in layout.get_mebers(): + memberNames.add(memberName) + + + jsonMembernames = {} + for memberName in hostgroupNames: + if not memberName in self.jsonDict[KEY_MEMBERS]: + self.log.w("Member " + memberName + " not found!") + for hostgroup in self.hostgroups: + if memberName in hostgroup.members: + del hostgroup.members[hostgroup.members.index(hgName)] + jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] + + self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) + \ No newline at end of file diff --git a/linspector b/linspector index 4a9d4f9..6009a4b 100755 --- a/linspector +++ b/linspector @@ -9,7 +9,7 @@ import logging import subprocess as sp from lib.core.job import JobInfo from lib.core.logger import Logger -from lib.config.config import Config +from lib.config.parser import ConfigParser from apscheduler.scheduler import Scheduler @@ -58,19 +58,9 @@ def main(): scheduler.start() log.i("starting linspector: reading config... (" + args.config + ")") - config = Config(args.config, log) + config_parser = ConfigParser(log) + config = config_parser.parse_config(args.config) log.d("parsed config: " + str(config)) - for hg in config.hostgroups: - - for hostGroupService in hg.services: - log.d(hostGroupService) - jobInfo = JobInfo(hg.name, hg.members, hg.hosts, hostGroupService.services, hg.threshold, hg.parent) - jobInfo.setLogger(log) - for period in hostGroupService.periods: - log.d(period) - jobs.append(period.createJob(scheduler, jobInfo, handleJob)) - for job in jobs: - log.d(str(job)) while True: time.sleep(10) From 2dbddaaf581184b8628ec4b23ae89235e4cae693 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 11 Jun 2013 04:52:20 +0200 Subject: [PATCH 096/268] sexy, sexy, sexy... --- lib/config/layouts.py | 15 +++++++++--- lib/config/parser.py | 53 +++++++++++++++++++++++-------------------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/lib/config/layouts.py b/lib/config/layouts.py index df47d30..a812cd5 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -1,19 +1,25 @@ -class LayouException(Exception): +class LayoutException(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return repr(self.msg) + class Layout: - def __init__(self, name, enabled = False , hostgroups=None): + def __init__(self, name, enabled=False, hostgroups=None, members=None): self._name = name self._enabled = enabled if hostgroups is None or len(hostgroups) <= 0: - raise Exception("Layout: " + name + " without hostgroups is useless") + raise LayoutException("Layout: " + self._name + " without hostgroups is useless") else: self._hostgroups = hostgroups + + if members is None or len(members) <= 0: + raise LayoutException("Layout: " + self._name + " without members is useless") + else: + self._members = members def get_name(self): return self._name @@ -24,6 +30,9 @@ class Layout: def get_hostgroups(self): return self._hostgroups + def get_members(self): + return self._members + def __str__(self): ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " " for group in self.hostgroups: diff --git a/lib/config/parser.py b/lib/config/parser.py index 72e893f..98f1de2 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -4,11 +4,12 @@ Created on Jun 9, 2013 @author: Rafael Timmerberg(raffn1+linspector@gmail.com) ''' -import os, os.path as path +from os.path import isfile import json from layouts import Layout from hostgroups import HostGroup + class ConfigurationException(Exception): def __init__(self, msg, log): log.e(msg) @@ -25,7 +26,6 @@ KEY_PERIODS = "periods" KEY_CORE = "core" - class ConfigParser: def __init__(self, log): ''' @@ -38,8 +38,7 @@ class ConfigParser: self.hostgroups = {} self.members = {} self.periods = {} - - + def _read_json_config(self, configFilename): ''' reads the config File and returns a dictionary, while lowering the first keys @@ -47,7 +46,7 @@ class ConfigParser: params: configFilename: the path under which the configuration file should be found ''' - if not path.isfile(configFilename): + if not isfile(configFilename): msg = "config file not found at " + str(configFilename) raise ConfigurationException(msg, self.log) @@ -59,8 +58,6 @@ class ConfigParser: self.log.i("reading Config: " + configFilename) return json.loads(config) - - def _get_as_list(self, configValue): ''' In some cases the config permits to define a list or a single value. @@ -68,7 +65,6 @@ class ConfigParser: returns the value as list ''' return configValue if isinstance(configValue, list) else [configValue] - def create_layouts_from_json(self, jsonLayouts): layouts = [] @@ -76,11 +72,10 @@ class ConfigParser: try: layout = Layout(lName, **lValues) layouts.append(layout) - except Exception: + except ConfigurationException: self.log.w("ignoring Layout " + lName + "! reason:") self.log.w(str(Exception)) return layouts - def create_hostgroups_from_json(self, jsonHostGroups): ''' @@ -91,14 +86,25 @@ class ConfigParser: try: hostgroup = HostGroup(hgName, **hgValues) hostgroups.append(hostgroup) - except Exception: + except ConfigurationException: self.log.w("ignoring hostgroup: " + hgName + "!") self.log.w("reason: " + str(Exception)) return hostgroups - - - - + + def create_members_from_json(self, jsonMembers): + ''' + creates Members from the jsonConfig + ''' + members = [] + for memberName, memberValues in jsonMembers.items(): + try: + member = memberName(memberName, **memberValues) + members.append(member) + except ConfigurationException: + self.log.w("ignoring member: " + memberName + "!") + self.log.w("reason: " + str(Exception)) + return members + def parse_config(self, configFilename): ''' parses the json configuration and returns a list of layouts, @@ -135,19 +141,18 @@ class ConfigParser: self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) memberNames = set() - for hostgroup in self.hostgroups: - for memberName in layout.get_mebers(): + for layout in layouts: + for memberName in layout.get_members(): memberNames.add(memberName) - - - jsonMembernames = {} - for memberName in hostgroupNames: + + jsonMembers = {} + for memberName in memberNames: if not memberName in self.jsonDict[KEY_MEMBERS]: self.log.w("Member " + memberName + " not found!") for hostgroup in self.hostgroups: if memberName in hostgroup.members: - del hostgroup.members[hostgroup.members.index(hgName)] - jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] + del hostgroup.members[hostgroup.members.index(memberName)] + jsonMembers[memberName] = self.jsonDict[KEY_HOSTGROUPS][memberName] - self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) + self.members = self.create_members_from_json(jsonMembers) \ No newline at end of file From 5a04595843c00417f06eda34c60cdb32fac16293 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 11 Jun 2013 04:53:42 +0200 Subject: [PATCH 097/268] sorry! from last commit message. added some member stuff to parser.py and layouts.py. --- lib/config/parser.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 98f1de2..5bde4b5 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,9 +1,3 @@ -''' -Created on Jun 9, 2013 - -@author: Rafael Timmerberg(raffn1+linspector@gmail.com) -''' - from os.path import isfile import json from layouts import Layout From 127dacd7780152fbc9a8c34ef8cb61c409cc218b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 00:10:14 +0200 Subject: [PATCH 098/268] big change n parsing logic passing --- lib/config/config.py | 4 +- lib/config/hostgroups.py | 66 ++++++++++++- lib/config/layouts.py | 9 ++ lib/config/members.py | 20 +++- lib/config/parser.py | 184 +++++++++++++++++++++++++++++++++++-- lib/config/periods.py | 23 +---- lib/processors/mongodb.py | 9 +- lib/services/http.py | 54 ++++++----- lib/services/ping.py | 11 ++- lib/services/service.py | 105 ++++++++++++++++++++- lib/services/shell.py | 22 +++-- lib/services/snmpget.py | 77 +++++++++------- lib/services/ssh.py | 22 +++-- lib/services/tcpconnect.py | 22 +++-- lib/tasks/email.py | 23 ++++- lib/tasks/sms.py | 23 ++++- lib/tasks/xmpp.py | 23 ++++- 17 files changed, 570 insertions(+), 127 deletions(-) diff --git a/lib/config/config.py b/lib/config/config.py index dfb91dc..4ce130e 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -1,7 +1,7 @@ import json from tasks import parseTaskList from members import parseMemberList -from periods import parsePeriodList + #from hostgroups import parseHostGroupList #from layouts import parseLayoutList @@ -17,7 +17,7 @@ class Config: self.tasks = parseTaskList(self.dict['tasks']) self.members = parseMemberList(self.dict['members'], self.tasks, log) - self.periods = parsePeriodList(self.dict['periods'], log) + #self.periods = parsePeriodList(self.dict['periods'], log) #self.hostgroups = parseHostGroupList(self.dict['hostgroups'], # self.members, # self.periods, diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 6614a91..487fd90 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -1,3 +1,4 @@ + class HostGroupException(Exception): def __init__(self, msg): self.msg = msg @@ -12,25 +13,80 @@ class HostGroupMissingArgumentException(HostGroupException): class HostGroup: def __init__(self, name, **kwargs): self.name = name - tmp = "members" + self.members = [] if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) - self.members = kwargs[tmp] + self.add_members(kwargs[tmp]) tmp = "hosts" + self.hosts = [] if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) - self.hosts = kwargs[tmp] + self.add_hosts(kwargs[tmp]) tmp = "services" if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) - self.services = kwargs[tmp] + self.add_services(kwargs[tmp]) + self.parents = [] + tmp = "parents" + if tmp in kwargs: + self.add_parent(kwargs[tmp]) + tmp = "processors" + self.processors = [] + if tmp in kwargs: + self.add_processor(kwargs[tmp]) + + def _to_config_dict(self, configDict): + me = {} + me["members"] = [member.nameid for member in self.get_members()] + me["hosts"] = self.hosts + me["parents"] = [hg.get_name() for hg in self.get_parents()] + #TODO implement delegation + #me["services"] = [service._to_config_dict(configDict) for service in self.get_services()] + #me["processors"] = [processor._to_config_dict(configDict) for processor in self.get_processors()] + configDict["hostgroups"][self.get_name()] = me + + + + def __add_internal(self,l,item): + if isinstance(item, list): + l.extend(item) + else: + l.append(item) + + def add_members(self, member): + self.__add_internal(self.get_members(), member) + + def add_hosts(self, host): + self.__add_internal(self.get_hosts(), host) + + def add_processors(self, processor): + self.__add_internal(self.get_processors(), processor) + + def add_parents(self, parent): + self.__add_internal(self.get_parents(), parent) + + def get_parents(self): + return self.parents + + def get_processors(self): + return self.processors + + def get_services(self): + return self.services + + def get_hosts(self): + return self.hosts + + def get_name(self): + return self.name + def get_members(self): - return self.members + return self.members def __str__(self): diff --git a/lib/config/layouts.py b/lib/config/layouts.py index a812cd5..afeb869 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -21,6 +21,15 @@ class Layout: else: self._members = members + def _to_config_dict(self, configDict): + me = {} + me["hostgroups"] = [hg.name for hg in self.get_hostgroups()] + me["enabled"] = self.is_enabled() + configDict["layouts"][self.get_name()] = me + for hostgroup in self.get_hostgroups(): + hostgroup._to_config_dict(configDict) + + def get_name(self): return self._name diff --git a/lib/config/members.py b/lib/config/members.py index 9526251..cfcf9c0 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -2,19 +2,33 @@ import re class Member: - def __init__(self, nameid, name="", phone="", comment="", parent="", filters=None): - self.nameid = nameid + def __init__(self, nameid, name="", phone="", comment="", parent="", tasks=None): + self.id = id self.name = name self.phone = phone - self.filters = filters + self.tasks = [] + self.add_task(tasks) self.comment = comment self.parent = parent + + def add_task(self, task): + if task is None: + return + if isinstance(task, list): + self.tasks.extend(task) + else: + self.tasks.append(task) + + def get_tasks(self): + return self.tasks 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: diff --git a/lib/config/parser.py b/lib/config/parser.py index 5bde4b5..0d0dbe1 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,9 +1,36 @@ from os.path import isfile import json +import imp +import sys + from layouts import Layout from hostgroups import HostGroup +from members import Member +from periods import CronPeriod, DatePeriod, IntervalPeriod +from lib.services.service import Service +from lib.processors.processor import Processor +from lib.parsers.parser import Parser +from lib.tasks.task import Task +from platform import processor + +MOD_SERVICES = "services" +MOD_PROCESSORS = "processors" +MOD_PARSERS = "parsers" +MOD_TASKS = "tasks" + +sys.path.append("../" + MOD_SERVICES) +sys.path.append("../" + MOD_PROCESSORS) +sys.path.append("../" + MOD_PARSERS) +sys.path.append("../" + MOD_TASKS) + +KEY_LAYOUTS = "layouts" +KEY_HOSTGROUPS = "hostgroups" +KEY_MEMBERS = "members" +KEY_PERIODS = "periods" +KEY_CORE = "core" + class ConfigurationException(Exception): def __init__(self, msg, log): log.e(msg) @@ -13,11 +40,8 @@ class ConfigurationException(Exception): return repr(self.msg) -KEY_LAYOUTS = "layouts" -KEY_HOSTGROUPS = "hostgroups" -KEY_MEMBERS = "members" -KEY_PERIODS = "periods" -KEY_CORE = "core" + + class ConfigParser: @@ -32,6 +56,16 @@ class ConfigParser: self.hostgroups = {} self.members = {} self.periods = {} + self.layouts = {} + self._loadedMods={MOD_SERVICES:{}, MOD_PROCESSORS:{}, MOD_TASKS:{}} + + def _create_new_config_dict(self): + return {"members": {}, "periods":{}, "hostgroups":{}, "layouts":{}, "core":{}} + + def create_config(self, config): + configDict = self._create_new_config_dict() + for layout in config.get_layouts(): + layout._to_config_dict(configDict) def _read_json_config(self, configFilename): ''' @@ -59,7 +93,18 @@ class ConfigParser: returns the value as list ''' return configValue if isinstance(configValue, list) else [configValue] - + + def _create_raw_Object(self, jsonDict, msgName, creator): + items = [] + for key, val in jsonDict.items(): + try: + item = creator(key, val) + items.append(item) + except Exception: + self.log.w("ignoring " + msgName + ": " + key + "! reason:") + self.log.w(str(Exception)) + return items + def create_layouts_from_json(self, jsonLayouts): layouts = [] for lName, lValues in jsonLayouts.items(): @@ -98,11 +143,46 @@ class ConfigParser: self.log.w("ignoring member: " + memberName + "!") self.log.w("reason: " + str(Exception)) return members + + def _load_module(self, clazz, modPart): + mods = self._loadedMods[modPart] + if clazz in mods: + return mods["class"] + else: + return __import__(clazz) + + def replace_with_import(self, objList, modPart, items_func, class_check): + loadedModules = {} + for obj in objList: + repl = [] + items = items_func(obj) + for clazzItem in items: + try: + clazz = clazzItem["class"] + mod = self._load_module(clazz, modPart) + item = mod.create(**clazzItem) + if class_check(item): + repl.append(item) + else: + self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + except ImportError, err: + self.log.w("could not import " + clazz + ": " + str(clazzItem) + "! reason") + self.log.w(str(err)) + except KeyError: + self.log.w("Key 'class' not in classItem " + str(clazzItem)) + except Exception: + self.log.w("Error while replace: " + str(Exception)) + del items[:] + items.extend(repl) + + + def parse_config(self, configFilename): ''' parses the json configuration and returns a list of layouts, which contains all nessesary information of the config file. + It will only parse nessesary Objects. Parsing will be done in 3 steps: 1. get raw Config Objects by just passing the values defined inside the config 2. replace references by objects @@ -115,6 +195,7 @@ class ConfigParser: self.jsonDict = self._read_json_config(configFilename) jsonLayouts = self.jsonDict[KEY_LAYOUTS] + #layouts = self._create_raw_Object(jsonLayouts, "Layouts", lambda name, vals: Layout(name, **vals)) layouts = self.create_layouts_from_json(jsonLayouts) hostgroupNames = set() @@ -149,4 +230,93 @@ class ConfigParser: jsonMembers[memberName] = self.jsonDict[KEY_HOSTGROUPS][memberName] self.members = self.create_members_from_json(jsonMembers) - \ No newline at end of file + + +def parsePeriodList(name, values): + if "date" in values: + return DatePeriod(name, **values) + + comp = ["weeks", "days", "hours", "minutes", "seconds", "start_date"] + if len([i for i in comp if i in values]) > 0 : + return IntervalPeriod(name, **values) + + comp = ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"] + if len([i for i in comp if i in values]) > 0 : + return CronPeriod(name, **values) + + else: + raise ConfigurationException("could not determine correct Period(" + repr(values)+").") + + + +class FullConfigParser(ConfigParser): + + + + def parse_config(self, configFilename): + ''' + parses the json configuration and returns a list of layouts, + which contains all nessesary information of the config file. + parses the full config + Parsing will be done in 3 steps: + 1. get raw Config Objects by just passing the values defined inside the config + 2. replace references by objects, import services, tasks, parsers and processors + 3. do sanity checks + + params: + configFilename: indicates which configuration file to parse + ''' + self.jsonDict = self._read_json_config(configFilename) + + # first step + creator = lambda name, values: Layout(name,**values) + layouts = self._create_raw_Object(self.jsonDict[KEY_LAYOUTS], "Layout", creator) + + creator = lambda name, values: Member(name, **values) + members = self._create_raw_Object(self.jsonDict[KEY_MEMBERS], "Member", creator) + + creator = lambda name, values: HostGroup(name, **values) + hostgroups = self._create_raw_Object(self.jsonDict[KEY_HOSTGROUPS], "Hostgroup", creator) + + creator = parsePeriodList + periods = self._create_raw_Object(self.jsonDict[KEY_PERIODS], "Period", creator) + + #2. import and replace + items_func = lambda hostgroup: hostgroup.get_services() + class_check = lambda service: isinstance(service, Service) + self.replace_with_import(hostgroups, MOD_SERVICES, items_func, class_check) + + items_func = lambda hostgroup: hostgroup.get_processors() + class_check = lambda processor: isinstance(processor, Processor) + self.replace_with_import(hostgroups, MOD_PROCESSORS, items_func, class_check) + + items_func = lambda service: service.get_parser() + class_check = lambda parser: isinstance(parser, Parser) + self.replace_with_import(hostgroups.services, MOD_PARSERS, items_func, class_check) + + items_func = lambda member: member.get_tasks() + class_check = lambda task: isinstance(task, Task) + self.replace_with_import(members, MOD_TASKS, items_func, class_check) + + for hg in hostgroups: + replmembers = [] + memberNames = hg.get_members() + for membername in memberNames: + member = [m for m in members if m.id == membername] + if len(member) == 1: + replmembers.append(member[0]) + + del hg.get_members()[:] + hg.add_members(replmembers) + + replParents = [] + parentNames = hg.get_parents() + for parentname in parentNames: + parent = [p for p in hostgroups if p.get_name() == parentname] + if len(parent) == 1: + replParents.append(parent[0]) + + + + + \ No newline at end of file diff --git a/lib/config/periods.py b/lib/config/periods.py index 2ee50bc..14c7651 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -69,26 +69,5 @@ class DatePeriod(Period): return scheduler.add_date_job(func, self.date, jobInfo) -def parsePeriodList(periodlist, log): - periods = [] - #log.d("values of periodslist: " + str(periodlist.items())) - for name, values in periodlist.items(): - - if "date" in values: - periods.append(DatePeriod(name, **values)) - continue - - comp = ["weeks", "days", "hours", "minutes", "seconds", "start_date"] - if len([i for i in comp if i in values]) > 0 : - periods.append(IntervalPeriod(name, **values)) - break - - comp = ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"] - if len([i for i in comp if i in values]) > 0 : - periods.append(CronPeriod(name, **values)) - break - else: - log.w("ignoring Period: " + str(name)) - log.w("reason: could not determine PeriodType: " + str(values)) - return periods + diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 28b5c85..1f3bf07 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -1,3 +1,10 @@ """ The MongoDB processor -""" \ No newline at end of file +""" + +from processor import Processor + +class Mongodb(Processor): + def __init__(self): + pass + \ No newline at end of file diff --git a/lib/services/http.py b/lib/services/http.py index 224f1a8..35ec6d2 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -13,37 +13,43 @@ from service import Service class HttpService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - if "string" in kwargs: - self.string = kwargs["string"] - else: - log.w("There is no string set to match") - raise - if "method" in kwargs: - self.method = kwargs["method"] - else: - self.method = "get" - if "params" in kwargs: + def __init__(self, **kwargs): + super(HttpService, self).__init__(**kwargs) + + args = self.get_arguments() + + self.method = "get" + if "method" in args: + self.method = args["method"] + + self.params = None + if "params" in args: self.params = kwargs["params"] - if "path" in kwargs: + + self.path = "/" + if "path" in args: self.path = kwargs["path"] - else: - self.path = "/" - if "port" in kwargs: + + self.port = "80" + if "port" in args: self.port = kwargs["port"] - else: - self.port = "80" - if "protocol" in kwargs: + + self.protocol = "http" + if "protocol" in args: self.protocol = kwargs["protocol"] - else: - self.protocol = "http" + + def needs_arguments(self): + return True + def execute(self): params = urllib.urlencode(self.params) if self.method is "get": - f = urllib.urlopen(self.protocol + "://" + self.host + ":" + self.port + self.path + "?%s" % params) + f = urllib.urlopen(self.protocol + "://" + self._host + ":" + self.port + self.path + "?%s" % params) elif self.method is "post": - f = urllib.urlopen(self.protocol + "://" + self.host + ":" + self.port + self.path, params) + f = urllib.urlopen(self.protocol + "://" + self._host + ":" + self.port + self.path, params) - #print f.read() \ No newline at end of file + #print f.read() + +def create(**kwargs): + return HttpService(**kwargs) \ No newline at end of file diff --git a/lib/services/ping.py b/lib/services/ping.py index 7cc0b51..fcfa0d3 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -2,4 +2,13 @@ The ping service in pure Python. """ -# http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ \ No newline at end of file +# http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ +from service import Service + +class PingService(Service): + def __init__(self, **kwargs): + super(PingService, self).__init__(**kwargs) + + +def create(self, **kwargs): + return PingService(**kwargs) diff --git a/lib/services/service.py b/lib/services/service.py index a2f15a4..81b3015 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -1,9 +1,103 @@ + +KEY_PARSER = "parser" +KEY_COMMENT = "comment" +KEY_THRESHOLD = "threshold" +KEY_FAILS = "fails" +KEY_PERIODS = "periods" +KEY_ARGS = "args" + class Service: - def __init__(self, host, parser): - self.host = host - self.parser = parser + def __init__(self, **kwargs): + + self._args = {} + if KEY_ARGS in kwargs: + self.add_arguments(kwargs[KEY_ARGS]) + elif self.needs_arguments(): + raise Exception("Error: needs arguments but none provided!") + + self._host = None + + self._parser = [] + if KEY_PARSER in kwargs: + self.add_parser(kwargs[KEY_PARSER]) + + self._comment = None + if KEY_COMMENT in kwargs: + self._comment = kwargs[KEY_COMMENT] + + self._threshold = 0 + if KEY_THRESHOLD in kwargs: + self._threshold = kwargs[KEY_THRESHOLD] + + self._fails = {} + if KEY_FAILS in kwargs: + self.put_fails(kwargs[KEY_FAILS]) + + self._periods = [] + if KEY_PERIODS in kwargs: + self.addPeriods(kwargs[KEY_PERIODS]) + self.errorcode = 0 self.errormessage = "No Error!" + + def add_arguments(self, args): + for key, val in args.items(): + self._args[key] = val + + def add_argument(self, key, value): + self._args[key] = value + + def get_arguments(self): + return self._args + + def add_period(self, period): + if period is not None: + if isinstance(period, list): + self._periods.extend(period) + else: + self._periods.append(period) + + def get_periods(self): + return self._periods + + def get_fails(self): + return self._fails + + def has_fail(self, fail): + return fail in self.get_fails() + + def put_fail(self, key, value): + self._fails[key] = value + + def put_fails(self, fails): + for key, value in fails.items(): + self.put_fail(key, value) + + def get_threshold(self): + return self._threshold + + def get_comment(self): + return self._comment + + def set_host(self, host): + self._host = host + + def get_host(self): + return self._host + + def get_parser(self): + return self._parser + + + def add_parser(self, parser): + if parser is not None: + if isinstance(parser, list): + self._parser.extend(parser) + else: + self._parser.append(parser) + + def needs_arguments(self): + return False def _execute(self): self.pre_execute() @@ -18,7 +112,10 @@ class Service: pass def parse_result(self, executionResult): - return self.parser._parse(executionResult) + result = [] + for parser in self.get_parser(): + result.append(self._parser._parse(executionResult)) + def handle_result(self, parseResult): pass diff --git a/lib/services/shell.py b/lib/services/shell.py index 7b5c78c..f17255b 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -6,13 +6,21 @@ from service import Service class ShellService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - if "command" in kwargs: - self.command = kwargs["command"] + def __init__(self, **kwargs): + super(ShellService, self).__init__(**kwargs) + + args = self.get_arguments() + if "command" in args: + self.command = args["command"] else: - log.w("There is no command") - raise + raise Exception("There is no command argument") + + def needs_arguments(self): + return True + def execute(self): - self.command.call() \ No newline at end of file + self.command.call() + +def create(**kwargs): + return ShellService(**kwargs) \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index fde9f9d..98c3a17 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -2,45 +2,56 @@ The snmpget service in pure Python. """ -from pysnmp.entity.rfc3413.oneliner import cmdgen +#from pysnmp.entity.rfc3413.oneliner import cmdgen from service import Service +from Cython.Compiler.Naming import kwds_cname +from wx.lib.pubsub.core import kwargs class SnmpgetService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - if "community" in kwargs: - self.community = kwargs["community"] + def __init__(self, **kwargs): + super(SnmpgetService, self).__init__(**kwargs) + + args = self.get_arguments() + + if "community" in args: + self.community = args["community"] else: - log.w("There is no community") - raise - if "oid" in kwargs: - self.oid = kwargs["oid"] + raise Exception("There is no community") + + if "oid" in args: + self.oid = args["oid"] else: - log.w("There is no oid") - raise - if "port" in kwargs: - self.port = kwargs["port"] - else: - self.port = "161" + raise Exception("There is no oid") + + self.port = "161" + if "port" in args: + self.port = args["port"] + + def needs_arguments(self): + return True def execute(self): - cmdGen = cmdgen.CommandGenerator() + pass + #cmdGen = cmdgen.CommandGenerator() - errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( - cmdgen.CommunityData(self.community), - cmdgen.UdpTransportTarget((self.host, self.port)), - cmdgen.MibVariable(self.oid) - ) - - if errorIndication: - print(errorIndication) - else: - if errorStatus: - print('%s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBinds[int(errorIndex) - 1] or '?' - )) - else: - for name, val in varBinds: - print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) \ No newline at end of file + #errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( + # cmdgen.CommunityData(self.community), + # cmdgen.UdpTransportTarget((self._host, self.port)), + # cmdgen.MibVariable(self.oid) + #) + + #if errorIndication: + # print(errorIndication) + #else: + # if errorStatus: + # print('%s at %s' % ( + # errorStatus.prettyPrint(), + # errorIndex and varBinds[int(errorIndex) - 1] or '?' + # )) + # else: + # for name, val in varBinds: + # print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + +def create(**kargs): + return SnmpgetService(**kwargs) \ No newline at end of file diff --git a/lib/services/ssh.py b/lib/services/ssh.py index 3131571..c95ee44 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -11,14 +11,18 @@ from service import Service class SshService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - if "command" in kwargs: - self.command = kwargs["command"] + def __init__(self, **kwargs): + super(SshService, self).__init__(**kwargs) + + args = self.get_arguments() + if "command" in args: + self.command = args["command"] else: - log.w("There is no command") - raise - + raise Exception("There is no command argument") + + def needs_arguments(self): + return True + def execute(self): path = os.path.join(os.environ['HOME'], '.ssh', 'id_rsa') key = paramiko.RSAKey.from_private_key_file(path) @@ -35,7 +39,9 @@ class SshService(Service): print '... ' + line.strip('\n') client.close() - +def create(**kwargs): + return SshService(**kwargs) + # def main(): # # service = SshService(parser, log, command='uptime') # return diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 43b043c..d17322c 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -10,13 +10,18 @@ from service import Service class TcpconnectService(Service): - def __init__(self, parser, log, **kwargs): - super(Service, self).__init__(parser) - if "port" in kwargs: - self.port = kwargs["port"] + def __init__(self, **kwargs): + super(TcpconnectService, self).__init__(**kwargs) + + args = self.get_arguments() + if "port" in args: + self.port = args["port"] else: - log.w("There is no port set") - raise + raise Exception("There is no port set") + + + def needs_arguments(self): + return True def execute(self, log): try: @@ -32,4 +37,7 @@ class TcpconnectService(Service): self.errorcode = 2 sock.close() - return \ No newline at end of file + return + +def create(**kwargs): + return TcpconnectService(**kwargs) diff --git a/lib/tasks/email.py b/lib/tasks/email.py index d38e620..33975ea 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -1,3 +1,24 @@ """ The email task. -""" \ No newline at end of file +""" + +from lib.tasks.task import Task + +class EmailTask(Task): + def __init__(self, **kwargs): + if not "type" in kwargs: + raise Exception("'type' not in typeDict " + str(kwargs)) + if not "args" in kwargs: + raise Exception("typeDict " + str(kwargs) + " has nor arguments!") + self.set_task_type(kwargs["type"]) + self.recipient = kwargs["args"]["rcpt"] + + + + def execute_task(self, msg): + pass + + + +def creator(**taskDict): + return EmailTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 41f2d0c..6fff896 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -1,3 +1,24 @@ """ The sms task. -""" \ No newline at end of file +""" + +from task import Task + +class SmsTask(Task): + def __init__(self, **kwargs): + if not "type" in kwargs: + raise Exception("'type' not in typeDict " + str(kwargs)) + if not "args" in kwargs: + raise Exception("typeDict " + str(kwargs) + " has no arguments!") + self.set_task_type(kwargs["type"]) + self.recipient = kwargs["args"]["rcpt"] + + + + def execute_task(self, msg): + pass + + + +def creator(**taskDict): + return SmsTask(**taskDict) diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index 2bb064c..2a5ecfe 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -1,3 +1,24 @@ """ The xmpp task. -""" \ No newline at end of file +""" + +from task import Task + +class XmppTask(Task): + def __init__(self, **kwargs): + if not "type" in kwargs: + raise Exception("'type' not in typeDict " + str(kwargs)) + if not "args" in kwargs: + raise Exception("typeDict " + str(kwargs) + " has nor arguments!") + self.set_task_type(kwargs["type"]) + self.recipient = kwargs["args"]["rcpt"] + + + + def execute_task(self, msg): + pass + + + +def creator(**taskDict): + return XmppTask(taskDict) \ No newline at end of file From 25a1507bda52e9207b3a972f48daa2f06199e88b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 01:35:35 +0200 Subject: [PATCH 099/268] finished creation of parser, needs some bugfixes --- lib/config/parser.py | 61 ++++++++++++++++++++++++----------------- lib/services/snmpget.py | 2 -- linspector | 28 +++++++++++-------- 3 files changed, 52 insertions(+), 39 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 0d0dbe1..ee9174a 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -41,9 +41,6 @@ class ConfigurationException(Exception): - - - class ConfigParser: def __init__(self, log): ''' @@ -152,7 +149,6 @@ class ConfigParser: return __import__(clazz) def replace_with_import(self, objList, modPart, items_func, class_check): - loadedModules = {} for obj in objList: repl = [] items = items_func(obj) @@ -175,8 +171,22 @@ class ConfigParser: del items[:] items.extend(repl) - - + + def replace_pointer(self, objectList, replObjectList, id_list_func, id_get_func): + for obj in objectList: + replacements = [] + idList = id_list_func(obj) + for id in idList: + repl = [o for o in replObjectList if id == id_get_func(o)] + if len(repl) == 1: + replacements.append(repl[0]) + + del idList[:] + idList.extend(replacements) + + + + def parse_config(self, configFilename): ''' @@ -232,6 +242,8 @@ class ConfigParser: self.members = self.create_members_from_json(jsonMembers) + + def parsePeriodList(name, values): if "date" in values: return DatePeriod(name, **values) @@ -297,26 +309,25 @@ class FullConfigParser(ConfigParser): items_func = lambda member: member.get_tasks() class_check = lambda task: isinstance(task, Task) self.replace_with_import(members, MOD_TASKS, items_func, class_check) - + + #replace object pointer + id_list_func = lambda hostgroup: hostgroup.get_members() + id_get_func = lambda member: member.id + self.replace_pointer(hostgroups, members, id_list_func, id_get_func) + + services = [] for hg in hostgroups: - replmembers = [] - memberNames = hg.get_members() - for membername in memberNames: - member = [m for m in members if m.id == membername] - if len(member) == 1: - replmembers.append(member[0]) - - del hg.get_members()[:] - hg.add_members(replmembers) - - replParents = [] - parentNames = hg.get_parents() - for parentname in parentNames: - parent = [p for p in hostgroups if p.get_name() == parentname] - if len(parent) == 1: - replParents.append(parent[0]) - - + services.extend(hg.get_services()) + id_list_func = lambda service: service.get_periods() + id_get_func = lambda period: period.get_name() + self.replace_pointer(services, periods, id_list_func, id_get_func) + + id_list_func = lambda layout: layout.get_hostgroups() + id_get_func = lambda hostgroup: hostgroup.get_name() + self.replace_pointer(layouts, hostgroups, id_list_func, id_get_func) + + return layouts + \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index 98c3a17..e7fcc9d 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -4,8 +4,6 @@ The snmpget service in pure Python. #from pysnmp.entity.rfc3413.oneliner import cmdgen from service import Service -from Cython.Compiler.Naming import kwds_cname -from wx.lib.pubsub.core import kwargs class SnmpgetService(Service): diff --git a/linspector b/linspector index 6009a4b..8f1f377 100755 --- a/linspector +++ b/linspector @@ -1,4 +1,5 @@ #!/usr/bin/python2.7 -tt +from zenmapCore.UmitConf import config_parser __version__ = "0.4/TETRIS" __default_config__ = "./linspector.json" @@ -9,7 +10,7 @@ import logging import subprocess as sp from lib.core.job import JobInfo from lib.core.logger import Logger -from lib.config.parser import ConfigParser +from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler @@ -53,19 +54,22 @@ def main(): log.i("parsed arguments") if args.action == "start": - jobs = [] - scheduler = Scheduler() - scheduler.start() + configParser = FullConfigParser(log) + config = configParser.parse_config(args.config) + + #jobs = [] + #scheduler = Scheduler() + #scheduler.start() - log.i("starting linspector: reading config... (" + args.config + ")") - config_parser = ConfigParser(log) - config = config_parser.parse_config(args.config) - log.d("parsed config: " + str(config)) + #log.i("starting linspector: reading config... (" + args.config + ")") + #config_parser = ConfigParser(log) + #config = config_parser.parse_config(args.config) + #log.d("parsed config: " + str(config)) - while True: - time.sleep(10) - for job in jobs: - log.d(str(job)) + #while True: + # time.sleep(10) + # for job in jobs: + # log.d(str(job)) elif args.action == "stop": log.i("stopping linspector is currently unsupported") From ef526c98c51ff39a7ead893d976a19247db4132b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 01:50:01 +0200 Subject: [PATCH 100/268] added rest --- lib/config/parser.py | 2 +- lib/processors/processor.py | 8 +++++ lib/tasks/task.py | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 lib/processors/processor.py create mode 100644 lib/tasks/task.py diff --git a/lib/config/parser.py b/lib/config/parser.py index ee9174a..9d3b6dc 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -13,7 +13,7 @@ from lib.services.service import Service from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task -from platform import processor + MOD_SERVICES = "services" MOD_PROCESSORS = "processors" diff --git a/lib/processors/processor.py b/lib/processors/processor.py new file mode 100644 index 0000000..df61b44 --- /dev/null +++ b/lib/processors/processor.py @@ -0,0 +1,8 @@ +''' +Created on Jun 16, 2013 + +@author: rafael +''' +class Processor: + def __init__(self): + pass \ No newline at end of file diff --git a/lib/tasks/task.py b/lib/tasks/task.py new file mode 100644 index 0000000..78d8736 --- /dev/null +++ b/lib/tasks/task.py @@ -0,0 +1,60 @@ +''' +Created on Jun 15, 2013 + +@author: Rafael Timmerberg +''' + +class Task: + ''' + Base class for all built-in Tasks. + ''' + + def set_task_type(self, taskType): + ''' + sets the type of this task. + + Be aware! this method can only get called once! + + params: + taskType: the type of this task + ''' + if hasattr(self, "_taskType"): + raise Exception("taskType is only allowed to set once!") + self.taskType = taskType + + def get_task_type(self): + ''' + returns the type set by set_type_task + ''' + return self._taskType + + def execute_task(self, msg): + ''' + this is the method tasks usually override. + It gets called anytime the task should get executed + + default does nothing + + params: + msg: the msg for this task + ''' + pass + + def _execute(self,taskType, msg): + ''' + internal method which gets called for any member in a hostgroup. + It determines if it has an appropriate type by comparing taskType with get_task_type(). + Calls execute_task() if the type matches + + params: + taskType: the type of the fail which is compared with get_task_type() + msg: the error message + + return: + True if execute_task() is called succesfully, else False + ''' + if self.get_task_type() == taskType: + self.execute_task(msg) + return True + return False + \ No newline at end of file From 53659eb7a6e10a6088afc3774f083efce42a8a47 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 02:00:27 +0200 Subject: [PATCH 101/268] fixed layouts --- lib/config/layouts.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/config/layouts.py b/lib/config/layouts.py index afeb869..7dfa1f1 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -7,7 +7,7 @@ class LayoutException(Exception): class Layout: - def __init__(self, name, enabled=False, hostgroups=None, members=None): + def __init__(self, name, enabled=False, hostgroups=None): self._name = name self._enabled = enabled @@ -16,10 +16,6 @@ class Layout: else: self._hostgroups = hostgroups - if members is None or len(members) <= 0: - raise LayoutException("Layout: " + self._name + " without members is useless") - else: - self._members = members def _to_config_dict(self, configDict): me = {} @@ -39,8 +35,6 @@ class Layout: def get_hostgroups(self): return self._hostgroups - def get_members(self): - return self._members def __str__(self): ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " " From b5679c065e8b869487b8f180f3fc3ad2fc9c0bf9 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 02:16:04 +0200 Subject: [PATCH 102/268] fixed hostgroups --- lib/config/hostgroups.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 487fd90..7135125 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -26,6 +26,7 @@ class HostGroup: self.add_hosts(kwargs[tmp]) tmp = "services" + self.services = [] if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) self.add_services(kwargs[tmp]) @@ -33,12 +34,12 @@ class HostGroup: self.parents = [] tmp = "parents" if tmp in kwargs: - self.add_parent(kwargs[tmp]) + self.add_parents(kwargs[tmp]) tmp = "processors" self.processors = [] if tmp in kwargs: - self.add_processor(kwargs[tmp]) + self.add_processors(kwargs[tmp]) def _to_config_dict(self, configDict): me = {} @@ -69,6 +70,9 @@ class HostGroup: def add_parents(self, parent): self.__add_internal(self.get_parents(), parent) + + def add_services(self, services): + self.__add_internal(self.get_services(), services) def get_parents(self): return self.parents From b8d8a969c527f8c08e967b023fb10b860303446a Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 02:19:09 +0200 Subject: [PATCH 103/268] added module caching fix --- lib/config/parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 9d3b6dc..3fc90d9 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -146,7 +146,8 @@ class ConfigParser: if clazz in mods: return mods["class"] else: - return __import__(clazz) + mod[clazz] = __import__(clazz) + return mod def replace_with_import(self, objList, modPart, items_func, class_check): for obj in objList: From 42bdb0fb1e76d31d88ada4d9f332384015b02e61 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 02:19:50 +0200 Subject: [PATCH 104/268] added module caching fix --- lib/config/parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 3fc90d9..c332e4d 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -146,7 +146,8 @@ class ConfigParser: if clazz in mods: return mods["class"] else: - mod[clazz] = __import__(clazz) + mod = __import__(clazz) + mods[clazz] = mod return mod def replace_with_import(self, objList, modPart, items_func, class_check): From 2c407727964d5042f6807a1a66fb69b60f287cf4 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 18 Jun 2013 02:28:57 +0200 Subject: [PATCH 105/268] added module loading fix --- lib/config/parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index c332e4d..368f356 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -20,10 +20,10 @@ MOD_PROCESSORS = "processors" MOD_PARSERS = "parsers" MOD_TASKS = "tasks" -sys.path.append("../" + MOD_SERVICES) -sys.path.append("../" + MOD_PROCESSORS) -sys.path.append("../" + MOD_PARSERS) -sys.path.append("../" + MOD_TASKS) +sys.path.append("lib/" + MOD_SERVICES) +sys.path.append("lib/" + MOD_PROCESSORS) +sys.path.append("lib/" + MOD_PARSERS) +sys.path.append("lib/" + MOD_TASKS) KEY_LAYOUTS = "layouts" KEY_HOSTGROUPS = "hostgroups" From 883e59a3d120394d8351efdca6f896d4e66e921e Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 18 Jun 2013 02:58:40 +0200 Subject: [PATCH 106/268] whitespacing.... :) --- lib/config/hostgroups.py | 11 +++----- lib/config/hosts.py | 3 +- lib/config/layouts.py | 7 ++--- lib/config/members.py | 4 +-- lib/config/parser.py | 55 ++++++++++++------------------------- lib/config/periods.py | 6 +--- lib/parsers/parser.py | 1 - lib/processors/mongodb.py | 4 +-- lib/processors/processor.py | 6 ++-- lib/service/snmpget.py | 5 ---- lib/services/http.py | 4 +-- lib/services/ping.py | 3 +- lib/services/service.py | 7 ++--- lib/services/shell.py | 4 +-- lib/services/snmpget.py | 3 +- lib/services/ssh.py | 1 + lib/services/tcpconnect.py | 6 ++-- lib/tasks/email.py | 4 +-- lib/tasks/sms.py | 6 ++-- lib/tasks/task.py | 30 ++++++++++---------- lib/tasks/xmpp.py | 4 +-- linspector | 1 - 22 files changed, 66 insertions(+), 109 deletions(-) delete mode 100644 lib/service/snmpget.py diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 7135125..f6f6989 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -44,16 +44,14 @@ class HostGroup: def _to_config_dict(self, configDict): me = {} me["members"] = [member.nameid for member in self.get_members()] - me["hosts"] = self.hosts + me["hosts"] = self.hosts me["parents"] = [hg.get_name() for hg in self.get_parents()] #TODO implement delegation #me["services"] = [service._to_config_dict(configDict) for service in self.get_services()] #me["processors"] = [processor._to_config_dict(configDict) for processor in self.get_processors()] configDict["hostgroups"][self.get_name()] = me - - - - def __add_internal(self,l,item): + + def __add_internal(self, l, item): if isinstance(item, list): l.extend(item) else: @@ -91,7 +89,6 @@ class HostGroup: def get_members(self): return self.members - def __str__(self): ret = "HostGroup: " + self.name + " threshold: " + str(self.threshold) + " parent: " + self.parent + "\n" @@ -140,4 +137,4 @@ def parseHostGroupList(hostgroups, hosts, members, periods, services, log): hostGroupPeriods = [p for p in periods if p.name in servicePeriods] hostGroup.services.append(HostGroupService(services, hostGroupPeriods)) parsedHostGroups.append(hostGroup) - return parsedHostGroups + return parsedHostGroups \ No newline at end of file diff --git a/lib/config/hosts.py b/lib/config/hosts.py index afffc90..f507b1a 100644 --- a/lib/config/hosts.py +++ b/lib/config/hosts.py @@ -115,5 +115,4 @@ def parseHostList(hosts, services, log): log.w("Service " + servicename + " not defined in host " + host.name) #replace host.service member by parsed HostService Objects host.services = hostServices - return parsedHosts - + return parsedHosts \ No newline at end of file diff --git a/lib/config/layouts.py b/lib/config/layouts.py index 7dfa1f1..c045869 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -16,7 +16,6 @@ class Layout: else: self._hostgroups = hostgroups - def _to_config_dict(self, configDict): me = {} me["hostgroups"] = [hg.name for hg in self.get_hostgroups()] @@ -24,8 +23,7 @@ class Layout: configDict["layouts"][self.get_name()] = me for hostgroup in self.get_hostgroups(): hostgroup._to_config_dict(configDict) - - + def get_name(self): return self._name @@ -35,7 +33,6 @@ class Layout: def get_hostgroups(self): return self._hostgroups - def __str__(self): ret = "Layout: 'Name:" + str(self.name) + "', 'Enabled: " + str(self.enabled) + " " for group in self.hostgroups: @@ -78,4 +75,4 @@ class LayoutList: ret += "Plugins: " + str(self.plugins) + "\n" for layout in self.layouts: ret += str(layout) + "\n" - return ret + return ret \ No newline at end of file diff --git a/lib/config/members.py b/lib/config/members.py index cfcf9c0..33f193d 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -27,8 +27,6 @@ class Member: for f in self.filters: ret += str(f) return ret - - class MemberFilter: @@ -56,4 +54,4 @@ def parseMemberList(members, filters, log): if not found: log.w("filter: " + filtername + " is not defined in member " + member.name) member.filters = mFilter - return parsedMembers + return parsedMembers \ No newline at end of file diff --git a/lib/config/parser.py b/lib/config/parser.py index 368f356..535f764 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,6 +1,5 @@ from os.path import isfile import json -import imp import sys from layouts import Layout @@ -8,13 +7,11 @@ from hostgroups import HostGroup from members import Member from periods import CronPeriod, DatePeriod, IntervalPeriod - from lib.services.service import Service from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task - MOD_SERVICES = "services" MOD_PROCESSORS = "processors" MOD_PARSERS = "parsers" @@ -40,15 +37,14 @@ class ConfigurationException(Exception): return repr(self.msg) - class ConfigParser: def __init__(self, log): - ''' + """ initializes a new ConfigParser Object params: log: pre configured logger Object to post messages while parsing" - ''' + """ self.log = log self.hostgroups = {} self.members = {} @@ -65,12 +61,12 @@ class ConfigParser: layout._to_config_dict(configDict) def _read_json_config(self, configFilename): - ''' + """ reads the config File and returns a dictionary, while lowering the first keys params: configFilename: the path under which the configuration file should be found - ''' + """ if not isfile(configFilename): msg = "config file not found at " + str(configFilename) raise ConfigurationException(msg, self.log) @@ -84,11 +80,11 @@ class ConfigParser: return json.loads(config) def _get_as_list(self, configValue): - ''' + """ In some cases the config permits to define a list or a single value. returns the value as list - ''' + """ return configValue if isinstance(configValue, list) else [configValue] def _create_raw_Object(self, jsonDict, msgName, creator): @@ -114,9 +110,9 @@ class ConfigParser: return layouts def create_hostgroups_from_json(self, jsonHostGroups): - ''' + """ creates Hostgroups from the jsonConfig - ''' + """ hostgroups = [] for hgName, hgValues in jsonHostGroups.items(): try: @@ -128,9 +124,9 @@ class ConfigParser: return hostgroups def create_members_from_json(self, jsonMembers): - ''' + """ creates Members from the jsonConfig - ''' + """ members = [] for memberName, memberValues in jsonMembers.items(): try: @@ -172,7 +168,6 @@ class ConfigParser: self.log.w("Error while replace: " + str(Exception)) del items[:] items.extend(repl) - def replace_pointer(self, objectList, replObjectList, id_list_func, id_get_func): for obj in objectList: @@ -186,12 +181,8 @@ class ConfigParser: del idList[:] idList.extend(replacements) - - - - def parse_config(self, configFilename): - ''' + """ parses the json configuration and returns a list of layouts, which contains all nessesary information of the config file. It will only parse nessesary Objects. @@ -202,7 +193,7 @@ class ConfigParser: params: configFilename: indicates which configuration file to parse - ''' + """ self.jsonDict = self._read_json_config(configFilename) @@ -214,8 +205,7 @@ class ConfigParser: for layout in layouts: for hgName in layout.get_hostgroups(): hostgroupNames.add(hgName) - - + jsonHostgroups = {} for hgName in hostgroupNames: if not hgName in self.jsonDict[KEY_HOSTGROUPS]: @@ -244,8 +234,6 @@ class ConfigParser: self.members = self.create_members_from_json(jsonMembers) - - def parsePeriodList(name, values): if "date" in values: return DatePeriod(name, **values) @@ -257,18 +245,13 @@ def parsePeriodList(name, values): comp = ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"] if len([i for i in comp if i in values]) > 0 : return CronPeriod(name, **values) - else: raise ConfigurationException("could not determine correct Period(" + repr(values)+").") - - + class FullConfigParser(ConfigParser): - - - def parse_config(self, configFilename): - ''' + """ parses the json configuration and returns a list of layouts, which contains all nessesary information of the config file. parses the full config @@ -279,7 +262,7 @@ class FullConfigParser(ConfigParser): params: configFilename: indicates which configuration file to parse - ''' + """ self.jsonDict = self._read_json_config(configFilename) # first step @@ -328,8 +311,4 @@ class FullConfigParser(ConfigParser): id_get_func = lambda hostgroup: hostgroup.get_name() self.replace_pointer(layouts, hostgroups, id_list_func, id_get_func) - return layouts - - - - \ No newline at end of file + return layouts \ No newline at end of file diff --git a/lib/config/periods.py b/lib/config/periods.py index 14c7651..237a8fc 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -66,8 +66,4 @@ class DatePeriod(Period): return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_date_job(func, self.date, jobInfo) - - - - + return scheduler.add_date_job(func, self.date, jobInfo) \ No newline at end of file diff --git a/lib/parsers/parser.py b/lib/parsers/parser.py index 4c8feb4..977b284 100644 --- a/lib/parsers/parser.py +++ b/lib/parsers/parser.py @@ -1,4 +1,3 @@ - class Parser: def __init__(self): pass diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 1f3bf07..62eda3b 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -4,7 +4,7 @@ The MongoDB processor from processor import Processor + class Mongodb(Processor): def __init__(self): - pass - \ No newline at end of file + pass \ No newline at end of file diff --git a/lib/processors/processor.py b/lib/processors/processor.py index df61b44..988f696 100644 --- a/lib/processors/processor.py +++ b/lib/processors/processor.py @@ -1,8 +1,10 @@ -''' +""" Created on Jun 16, 2013 @author: rafael -''' +""" + + class Processor: def __init__(self): pass \ No newline at end of file diff --git a/lib/service/snmpget.py b/lib/service/snmpget.py deleted file mode 100644 index c36c477..0000000 --- a/lib/service/snmpget.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -The snmpget service in pure Python. -""" - -# http://pysnmp.sourceforge.net/ \ No newline at end of file diff --git a/lib/services/http.py b/lib/services/http.py index 35ec6d2..a23c42b 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -40,7 +40,6 @@ class HttpService(Service): def needs_arguments(self): return True - def execute(self): params = urllib.urlencode(self.params) @@ -50,6 +49,7 @@ class HttpService(Service): f = urllib.urlopen(self.protocol + "://" + self._host + ":" + self.port + self.path, params) #print f.read() - + + def create(**kwargs): return HttpService(**kwargs) \ No newline at end of file diff --git a/lib/services/ping.py b/lib/services/ping.py index fcfa0d3..fc07cc1 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -5,10 +5,11 @@ The ping service in pure Python. # http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ from service import Service + class PingService(Service): def __init__(self, **kwargs): super(PingService, self).__init__(**kwargs) def create(self, **kwargs): - return PingService(**kwargs) + return PingService(**kwargs) \ No newline at end of file diff --git a/lib/services/service.py b/lib/services/service.py index 81b3015..4d6d339 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -6,6 +6,7 @@ KEY_FAILS = "fails" KEY_PERIODS = "periods" KEY_ARGS = "args" + class Service: def __init__(self, **kwargs): @@ -87,8 +88,7 @@ class Service: def get_parser(self): return self._parser - - + def add_parser(self, parser): if parser is not None: if isinstance(parser, list): @@ -115,7 +115,6 @@ class Service: result = [] for parser in self.get_parser(): result.append(self._parser._parse(executionResult)) - def handle_result(self, parseResult): - pass + pass \ No newline at end of file diff --git a/lib/services/shell.py b/lib/services/shell.py index f17255b..59ad5e8 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -17,10 +17,10 @@ class ShellService(Service): def needs_arguments(self): return True - def execute(self): self.command.call() - + + def create(**kwargs): return ShellService(**kwargs) \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index e7fcc9d..bf516fb 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -50,6 +50,7 @@ class SnmpgetService(Service): # else: # for name, val in varBinds: # print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) - + + def create(**kargs): return SnmpgetService(**kwargs) \ No newline at end of file diff --git a/lib/services/ssh.py b/lib/services/ssh.py index c95ee44..dc82884 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -39,6 +39,7 @@ class SshService(Service): print '... ' + line.strip('\n') client.close() + def create(**kwargs): return SshService(**kwargs) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index d17322c..1548698 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -18,7 +18,6 @@ class TcpconnectService(Service): self.port = args["port"] else: raise Exception("There is no port set") - def needs_arguments(self): return True @@ -38,6 +37,7 @@ class TcpconnectService(Service): sock.close() return - + + def create(**kwargs): - return TcpconnectService(**kwargs) + return TcpconnectService(**kwargs) \ No newline at end of file diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 33975ea..4453b4a 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -4,6 +4,7 @@ The email task. from lib.tasks.task import Task + class EmailTask(Task): def __init__(self, **kwargs): if not "type" in kwargs: @@ -12,13 +13,10 @@ class EmailTask(Task): raise Exception("typeDict " + str(kwargs) + " has nor arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - - def execute_task(self, msg): pass - def creator(**taskDict): return EmailTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 6fff896..407f542 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -4,6 +4,7 @@ The sms task. from task import Task + class SmsTask(Task): def __init__(self, **kwargs): if not "type" in kwargs: @@ -12,13 +13,10 @@ class SmsTask(Task): raise Exception("typeDict " + str(kwargs) + " has no arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - - def execute_task(self, msg): pass - def creator(**taskDict): - return SmsTask(**taskDict) + return SmsTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/task.py b/lib/tasks/task.py index 78d8736..12d2269 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -1,35 +1,36 @@ -''' +""" Created on Jun 15, 2013 @author: Rafael Timmerberg -''' +""" + class Task: - ''' + """ Base class for all built-in Tasks. - ''' + """ def set_task_type(self, taskType): - ''' + """ sets the type of this task. Be aware! this method can only get called once! params: taskType: the type of this task - ''' + """ if hasattr(self, "_taskType"): raise Exception("taskType is only allowed to set once!") self.taskType = taskType def get_task_type(self): - ''' + """ returns the type set by set_type_task - ''' + """ return self._taskType def execute_task(self, msg): - ''' + """ this is the method tasks usually override. It gets called anytime the task should get executed @@ -37,11 +38,11 @@ class Task: params: msg: the msg for this task - ''' + """ pass - def _execute(self,taskType, msg): - ''' + def _execute(self, taskType, msg): + """ internal method which gets called for any member in a hostgroup. It determines if it has an appropriate type by comparing taskType with get_task_type(). Calls execute_task() if the type matches @@ -52,9 +53,8 @@ class Task: return: True if execute_task() is called succesfully, else False - ''' + """ if self.get_task_type() == taskType: self.execute_task(msg) return True - return False - \ No newline at end of file + return False \ No newline at end of file diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index 2a5ecfe..694b766 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -4,6 +4,7 @@ The xmpp task. from task import Task + class XmppTask(Task): def __init__(self, **kwargs): if not "type" in kwargs: @@ -12,13 +13,10 @@ class XmppTask(Task): raise Exception("typeDict " + str(kwargs) + " has nor arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - - def execute_task(self, msg): pass - def creator(**taskDict): return XmppTask(taskDict) \ No newline at end of file diff --git a/linspector b/linspector index 8f1f377..dbbfb89 100755 --- a/linspector +++ b/linspector @@ -1,5 +1,4 @@ #!/usr/bin/python2.7 -tt -from zenmapCore.UmitConf import config_parser __version__ = "0.4/TETRIS" __default_config__ = "./linspector.json" From 72798c18d26a8a0d86b709c72237288de3403f9d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 18 Jun 2013 03:08:37 +0200 Subject: [PATCH 107/268] docs update From 5d3652048d7039fd9d8d25aa459f407057f71ca2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 18 Jun 2013 05:36:13 +0200 Subject: [PATCH 108/268] added syslog processor... --- linspector.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linspector.json b/linspector.json index 3824198..1eae12e 100644 --- a/linspector.json +++ b/linspector.json @@ -36,6 +36,10 @@ { "class": "mongodb", "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default" } + }, + { + "class": "syslog", + "args":{ "host": "syslog.linspector.org", "user": "syslog", "password": "secret" } } ], "services":[ From 713de159e7368a85492416fdcd9b4b9c103307e8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 18 Jun 2013 05:39:37 +0200 Subject: [PATCH 109/268] the syslog file... i forgot... ;) --- lib/processors/syslog.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lib/processors/syslog.py diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py new file mode 100644 index 0000000..05b4665 --- /dev/null +++ b/lib/processors/syslog.py @@ -0,0 +1,10 @@ +""" +The syslog processor +""" + +from processor import Processor + + +class Syslog(Processor): + def __init__(self): + pass \ No newline at end of file From 0b34a14d530454a9f5900c0fdcfee4c840d12582 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 01:29:11 +0200 Subject: [PATCH 110/268] fixed parsing, replaced non_workin instance_check with todo --- lib/config/parser.py | 56 ++++++++++++++++++++++++-------------- lib/config/periods.py | 2 +- lib/parsers/parser.py | 1 + lib/processors/mongodb.py | 6 +++- lib/processors/syslog.py | 5 +++- lib/services/ping.py | 4 +-- lib/services/service.py | 8 +++--- lib/services/shell.py | 2 +- lib/services/snmpget.py | 2 +- lib/services/ssh.py | 2 +- lib/services/tcpconnect.py | 4 ++- lib/tasks/email.py | 2 +- lib/tasks/sms.py | 2 +- lib/tasks/xmpp.py | 3 +- 14 files changed, 63 insertions(+), 36 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 535f764..5fc958d 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,13 +1,17 @@ from os.path import isfile import json import sys - +from os.path import join +from os import getcwd +import imp from layouts import Layout from hostgroups import HostGroup +import lib.services.ping from members import Member from periods import CronPeriod, DatePeriod, IntervalPeriod from lib.services.service import Service +print id(Service) from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task @@ -17,10 +21,7 @@ MOD_PROCESSORS = "processors" MOD_PARSERS = "parsers" MOD_TASKS = "tasks" -sys.path.append("lib/" + MOD_SERVICES) -sys.path.append("lib/" + MOD_PROCESSORS) -sys.path.append("lib/" + MOD_PARSERS) -sys.path.append("lib/" + MOD_TASKS) + KEY_LAYOUTS = "layouts" KEY_HOSTGROUPS = "hostgroups" @@ -143,6 +144,8 @@ class ConfigParser: return mods["class"] else: mod = __import__(clazz) + #path = join("lib", modPart, clazz + ".py") + #mod = imp.load_source(clazz, path) mods[clazz] = mod return mod @@ -153,19 +156,28 @@ class ConfigParser: for clazzItem in items: try: clazz = clazzItem["class"] + path = "lib/" + modPart + sys.path.append(path) mod = self._load_module(clazz, modPart) - item = mod.create(**clazzItem) - if class_check(item): - repl.append(item) - else: - self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + item = mod.create(clazzItem) + repl.append(item) + #TODO: activate the crappy classcheck if answer is provided + #http://stackoverflow.com/questions/17179440/ + self.log.d("warning: instance_check isn't working yet! TRUST_ALL = TRUE") + #if class_check(item): + # repl.append(item) + #else: + # self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") except ImportError, err: self.log.w("could not import " + clazz + ": " + str(clazzItem) + "! reason") self.log.w(str(err)) - except KeyError: - self.log.w("Key 'class' not in classItem " + str(clazzItem)) - except Exception: - self.log.w("Error while replace: " + str(Exception)) + except KeyError, k: + self.log.w("Key '" + str(k) + "' not in classItem " + str(clazzItem)) + except Exception, e: + self.log.w("Error while replace: " + str(e)) + finally: + if path in sys.path: + del sys.path[sys.path.index(path)] del items[:] items.extend(repl) @@ -277,7 +289,8 @@ class FullConfigParser(ConfigParser): creator = parsePeriodList periods = self._create_raw_Object(self.jsonDict[KEY_PERIODS], "Period", creator) - + + #2. import and replace items_func = lambda hostgroup: hostgroup.get_services() class_check = lambda service: isinstance(service, Service) @@ -286,10 +299,15 @@ class FullConfigParser(ConfigParser): items_func = lambda hostgroup: hostgroup.get_processors() class_check = lambda processor: isinstance(processor, Processor) self.replace_with_import(hostgroups, MOD_PROCESSORS, items_func, class_check) - + + services = [] + for hg in hostgroups: + services.extend(hg.get_services()) + + items_func = lambda service: service.get_parser() class_check = lambda parser: isinstance(parser, Parser) - self.replace_with_import(hostgroups.services, MOD_PARSERS, items_func, class_check) + self.replace_with_import(services, MOD_PARSERS, items_func, class_check) items_func = lambda member: member.get_tasks() class_check = lambda task: isinstance(task, Task) @@ -300,9 +318,7 @@ class FullConfigParser(ConfigParser): id_get_func = lambda member: member.id self.replace_pointer(hostgroups, members, id_list_func, id_get_func) - services = [] - for hg in hostgroups: - services.extend(hg.get_services()) + id_list_func = lambda service: service.get_periods() id_get_func = lambda period: period.get_name() self.replace_pointer(services, periods, id_list_func, id_get_func) diff --git a/lib/config/periods.py b/lib/config/periods.py index 237a8fc..a0c2a56 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -2,7 +2,7 @@ class Period(object): def __init__(self, name): self.name = name - def getName(self): + def get_name(self): return self.name def createJob(self, scheduler, jobInfo, func): diff --git a/lib/parsers/parser.py b/lib/parsers/parser.py index 977b284..335b596 100644 --- a/lib/parsers/parser.py +++ b/lib/parsers/parser.py @@ -11,3 +11,4 @@ class Parser: def generate_parse_result(self, result): pass + diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 62eda3b..c94c84c 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -7,4 +7,8 @@ from processor import Processor class Mongodb(Processor): def __init__(self): - pass \ No newline at end of file + pass + + +def create(kwargs): + return Mongodb(**kwargs) \ No newline at end of file diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index 05b4665..e2d0371 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -7,4 +7,7 @@ from processor import Processor class Syslog(Processor): def __init__(self): - pass \ No newline at end of file + pass + +def create(kwargs): + return Syslog(**kwargs) diff --git a/lib/services/ping.py b/lib/services/ping.py index fc07cc1..69d7f31 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -8,8 +8,8 @@ from service import Service class PingService(Service): def __init__(self, **kwargs): - super(PingService, self).__init__(**kwargs) + Service.__init__(self, **kwargs) -def create(self, **kwargs): +def create(kwargs): return PingService(**kwargs) \ No newline at end of file diff --git a/lib/services/service.py b/lib/services/service.py index 4d6d339..f77fef1 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -7,7 +7,7 @@ KEY_PERIODS = "periods" KEY_ARGS = "args" -class Service: +class Service(object): def __init__(self, **kwargs): self._args = {} @@ -36,10 +36,10 @@ class Service: self._periods = [] if KEY_PERIODS in kwargs: - self.addPeriods(kwargs[KEY_PERIODS]) + self.add_periods(kwargs[KEY_PERIODS]) self.errorcode = 0 - self.errormessage = "No Error!" + self.errormessage = None def add_arguments(self, args): for key, val in args.items(): @@ -51,7 +51,7 @@ class Service: def get_arguments(self): return self._args - def add_period(self, period): + def add_periods(self, period): if period is not None: if isinstance(period, list): self._periods.extend(period) diff --git a/lib/services/shell.py b/lib/services/shell.py index 59ad5e8..a1ebc32 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -22,5 +22,5 @@ class ShellService(Service): self.command.call() -def create(**kwargs): +def create(kwargs): return ShellService(**kwargs) \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index bf516fb..15a0d7c 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -52,5 +52,5 @@ class SnmpgetService(Service): # print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) -def create(**kargs): +def create(kargs): return SnmpgetService(**kwargs) \ No newline at end of file diff --git a/lib/services/ssh.py b/lib/services/ssh.py index dc82884..44116a1 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -40,7 +40,7 @@ class SshService(Service): client.close() -def create(**kwargs): +def create(kwargs): return SshService(**kwargs) # def main(): diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 1548698..3fcf151 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -6,11 +6,13 @@ not use a parser. """ import socket +from lib.config.services import Service from service import Service class TcpconnectService(Service): def __init__(self, **kwargs): + #Service.__init__(self, **kwargs) super(TcpconnectService, self).__init__(**kwargs) args = self.get_arguments() @@ -39,5 +41,5 @@ class TcpconnectService(Service): return -def create(**kwargs): +def create(kwargs): return TcpconnectService(**kwargs) \ No newline at end of file diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 4453b4a..8593c84 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -18,5 +18,5 @@ class EmailTask(Task): pass -def creator(**taskDict): +def creator(taskDict): return EmailTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 407f542..d352204 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -18,5 +18,5 @@ class SmsTask(Task): pass -def creator(**taskDict): +def creator(taskDict): return SmsTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index 694b766..4f3fc67 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -18,5 +18,6 @@ class XmppTask(Task): pass -def creator(**taskDict): + +def creator(taskDict): return XmppTask(taskDict) \ No newline at end of file From 3fee020d46032d5cc9b30c04b9fbf778f70c02c2 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 01:39:25 +0200 Subject: [PATCH 111/268] improved logging, fixed creator to create --- lib/config/parser.py | 2 +- lib/tasks/email.py | 2 +- lib/tasks/sms.py | 2 +- lib/tasks/xmpp.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 5fc958d..0fd1d45 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -174,7 +174,7 @@ class ConfigParser: except KeyError, k: self.log.w("Key '" + str(k) + "' not in classItem " + str(clazzItem)) except Exception, e: - self.log.w("Error while replace: " + str(e)) + self.log.w("Error while replace: " + clazz + str(e)) finally: if path in sys.path: del sys.path[sys.path.index(path)] diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 8593c84..01db30c 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -18,5 +18,5 @@ class EmailTask(Task): pass -def creator(taskDict): +def create(taskDict): return EmailTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index d352204..49dd80e 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -18,5 +18,5 @@ class SmsTask(Task): pass -def creator(taskDict): +def create(taskDict): return SmsTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index 4f3fc67..f6f2477 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -19,5 +19,5 @@ class XmppTask(Task): -def creator(taskDict): +def create(taskDict): return XmppTask(taskDict) \ No newline at end of file From e2ab9709c135fa841819129bf65cecda9b72d630 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 01:56:04 +0200 Subject: [PATCH 112/268] just cleanup --- lib/config/parser.py | 103 ++----------------------------------------- linspector.json | 2 +- 2 files changed, 4 insertions(+), 101 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 0fd1d45..27fd23f 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,12 +1,9 @@ from os.path import isfile import json import sys -from os.path import join -from os import getcwd import imp from layouts import Layout from hostgroups import HostGroup -import lib.services.ping from members import Member from periods import CronPeriod, DatePeriod, IntervalPeriod @@ -51,10 +48,10 @@ class ConfigParser: self.members = {} self.periods = {} self.layouts = {} - self._loadedMods={MOD_SERVICES:{}, MOD_PROCESSORS:{}, MOD_TASKS:{}} + self._loadedMods={MOD_SERVICES: {}, MOD_PROCESSORS: {}, MOD_TASKS: {}, MOD_PARSERS: {}} def _create_new_config_dict(self): - return {"members": {}, "periods":{}, "hostgroups":{}, "layouts":{}, "core":{}} + return {"members": {}, "periods": {}, "hostgroups": {}, "layouts": {}, "core": {}} def create_config(self, config): configDict = self._create_new_config_dict() @@ -80,13 +77,6 @@ class ConfigParser: self.log.i("reading Config: " + configFilename) return json.loads(config) - def _get_as_list(self, configValue): - """ - In some cases the config permits to define a list or a single value. - - returns the value as list - """ - return configValue if isinstance(configValue, list) else [configValue] def _create_raw_Object(self, jsonDict, msgName, creator): items = [] @@ -98,45 +88,7 @@ class ConfigParser: self.log.w("ignoring " + msgName + ": " + key + "! reason:") self.log.w(str(Exception)) return items - - def create_layouts_from_json(self, jsonLayouts): - layouts = [] - for lName, lValues in jsonLayouts.items(): - try: - layout = Layout(lName, **lValues) - layouts.append(layout) - except ConfigurationException: - self.log.w("ignoring Layout " + lName + "! reason:") - self.log.w(str(Exception)) - return layouts - def create_hostgroups_from_json(self, jsonHostGroups): - """ - creates Hostgroups from the jsonConfig - """ - hostgroups = [] - for hgName, hgValues in jsonHostGroups.items(): - try: - hostgroup = HostGroup(hgName, **hgValues) - hostgroups.append(hostgroup) - except ConfigurationException: - self.log.w("ignoring hostgroup: " + hgName + "!") - self.log.w("reason: " + str(Exception)) - return hostgroups - - def create_members_from_json(self, jsonMembers): - """ - creates Members from the jsonConfig - """ - members = [] - for memberName, memberValues in jsonMembers.items(): - try: - member = memberName(memberName, **memberValues) - members.append(member) - except ConfigurationException: - self.log.w("ignoring member: " + memberName + "!") - self.log.w("reason: " + str(Exception)) - return members def _load_module(self, clazz, modPart): mods = self._loadedMods[modPart] @@ -194,56 +146,7 @@ class ConfigParser: idList.extend(replacements) def parse_config(self, configFilename): - """ - parses the json configuration and returns a list of layouts, - which contains all nessesary information of the config file. - It will only parse nessesary Objects. - Parsing will be done in 3 steps: - 1. get raw Config Objects by just passing the values defined inside the config - 2. replace references by objects - 3. do sanity checks - - params: - configFilename: indicates which configuration file to parse - """ - - self.jsonDict = self._read_json_config(configFilename) - - jsonLayouts = self.jsonDict[KEY_LAYOUTS] - #layouts = self._create_raw_Object(jsonLayouts, "Layouts", lambda name, vals: Layout(name, **vals)) - layouts = self.create_layouts_from_json(jsonLayouts) - - hostgroupNames = set() - for layout in layouts: - for hgName in layout.get_hostgroups(): - hostgroupNames.add(hgName) - - jsonHostgroups = {} - for hgName in hostgroupNames: - if not hgName in self.jsonDict[KEY_HOSTGROUPS]: - self.log.w("Hostgroup " + hgName + " not found!") - for layout in layouts: - if hgName in layout.hostgroups: - del layout.hostgroups[layout.hostgroups.index(hgName)] - jsonHostgroups[hgName] = self.jsonDict[KEY_HOSTGROUPS][hgName] - - self.hostgroups = self.create_hostgroups_from_json(jsonHostgroups) - - memberNames = set() - for layout in layouts: - for memberName in layout.get_members(): - memberNames.add(memberName) - - jsonMembers = {} - for memberName in memberNames: - if not memberName in self.jsonDict[KEY_MEMBERS]: - self.log.w("Member " + memberName + " not found!") - for hostgroup in self.hostgroups: - if memberName in hostgroup.members: - del hostgroup.members[hostgroup.members.index(memberName)] - jsonMembers[memberName] = self.jsonDict[KEY_HOSTGROUPS][memberName] - - self.members = self.create_members_from_json(jsonMembers) + pass def parsePeriodList(name, values): diff --git a/linspector.json b/linspector.json index 1eae12e..b1f464e 100644 --- a/linspector.json +++ b/linspector.json @@ -5,7 +5,7 @@ "comment": "The Linspector Admin", "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, - { "class": "xmpp", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] + { "class": "xmpp", "type": "critical", "arfixed parsing, replaced non_workin instance_check with gs":{ "rcpt": "admin@jabber.hanez.org" }}] }, "hanez":{ "name": "Johannes Findeisen", From a547de514767fb1c96d2b49cea29a1d825ee97ed Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 02:20:30 +0200 Subject: [PATCH 113/268] added some comments --- lib/config/parser.py | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 27fd23f..fb1361c 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -77,8 +77,16 @@ class ConfigParser: self.log.i("reading Config: " + configFilename) return json.loads(config) - def _create_raw_Object(self, jsonDict, msgName, creator): + """ + creates an Main object from the configuration, but just parses raw data and hands it to the object + + :param jsonDict: the configuration file part as dict + :param msgName: name of object for error message + :param creator: function pointer which is taking two arguments: identifier of the object and arguments. + :should return an object + :return: a list of objects returned by creator + """ items = [] for key, val in jsonDict.items(): try: @@ -89,8 +97,13 @@ class ConfigParser: self.log.w(str(Exception)) return items - def _load_module(self, clazz, modPart): + """ + imports and caches a module. + :param clazz: the filename of the module (i.e email, ping...) + :param modPart: the folder of the module. (i.e services, parsers...) + :return: the imported/cached module, or throws an error if it couldn't find it + """ mods = self._loadedMods[modPart] if clazz in mods: return mods["class"] @@ -102,6 +115,14 @@ class ConfigParser: return mod def replace_with_import(self, objList, modPart, items_func, class_check): + """ + replaces configuration dicts with their objects by importing and creating it in the first step. + In the second step the original list of json config dicts gets replaced by the loaded objects + :param objList: the list of objects which is iterated on + :param modPart: the folder from the module (i.e tasks, parsers) + :param items_func: function to get a pointer on the list of json-config-objects to replace. Takes one argument and + :param class_check: currently unsupported + """ for obj in objList: repl = [] items = items_func(obj) @@ -134,6 +155,13 @@ class ConfigParser: items.extend(repl) def replace_pointer(self, objectList, replObjectList, id_list_func, id_get_func): + """ + replaces objects from the config by ids. + :param objectList: the list of objects to be iterated on + :param replObjectList: the list of objects to replace + :param id_list_func: function taking one argument as object and should return a list of config ids to replace + :param id_get_func: function taking one config-object as argument and should return the config id to compare + """ for obj in objectList: replacements = [] idList = id_list_func(obj) From eef057a37e90030d5115948c5d7bed4a0e7952d5 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 02:25:37 +0200 Subject: [PATCH 114/268] improved error log --- lib/config/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index fb1361c..d3b6ac3 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -147,7 +147,7 @@ class ConfigParser: except KeyError, k: self.log.w("Key '" + str(k) + "' not in classItem " + str(clazzItem)) except Exception, e: - self.log.w("Error while replace: " + clazz + str(e)) + self.log.w("Error while replacing class ( " + clazz + " ):" + str(e)) finally: if path in sys.path: del sys.path[sys.path.index(path)] From ce631ad12d7b5f949365bc6619e81be6e6b4efa7 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 02:45:37 +0200 Subject: [PATCH 115/268] strange behavior, really really strange! I gues monthy python is coming from death to just kidding me! --- lib/config/parser.py | 13 +++++++++++-- lib/tasks/xmpp.py | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index d3b6ac3..746358f 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,4 +1,6 @@ from os.path import isfile +from os.path import join +from os import getcwd import json import sys import imp @@ -109,7 +111,8 @@ class ConfigParser: return mods["class"] else: mod = __import__(clazz) - #path = join("lib", modPart, clazz + ".py") + #path = join(getcwd(), "lib", modPart, clazz + ".py") + #self.log.w(path) #mod = imp.load_source(clazz, path) mods[clazz] = mod return mod @@ -128,6 +131,12 @@ class ConfigParser: items = items_func(obj) for clazzItem in items: try: + if "class" not in clazzItem: + self.log.w("python says class is not in class item!") + self.log.w(modPart) + self.log.w(clazzItem) + self.log.w(clazzItem["class"]) + clazz = clazzItem["class"] path = "lib/" + modPart sys.path.append(path) @@ -145,7 +154,7 @@ class ConfigParser: self.log.w("could not import " + clazz + ": " + str(clazzItem) + "! reason") self.log.w(str(err)) except KeyError, k: - self.log.w("Key '" + str(k) + "' not in classItem " + str(clazzItem)) + self.log.w("Key " + str(k) + " not in classItem " + str(clazzItem)) except Exception, e: self.log.w("Error while replacing class ( " + clazz + " ):" + str(e)) finally: diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index f6f2477..b5cf146 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -20,4 +20,4 @@ class XmppTask(Task): def create(taskDict): - return XmppTask(taskDict) \ No newline at end of file + return XmppTask(**taskDict) \ No newline at end of file From c463f2473d174e5a7ab6c46544e18ce096c61ad5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 03:26:25 +0200 Subject: [PATCH 116/268] whitespaces at night... --- lib/config/hostgroups.py | 5 +++-- lib/config/parser.py | 26 +++++++++++--------------- lib/core/command.py | 1 + lib/core/linspector_daemon.py | 2 +- lib/core/logger.py | 1 - lib/parsers/parser.py | 3 +-- lib/processors/processor.py | 4 +--- lib/processors/syslog.py | 3 ++- lib/tasks/email.py | 2 +- lib/tasks/task.py | 20 +++++++------------- lib/tasks/xmpp.py | 1 - 11 files changed, 28 insertions(+), 40 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index f6f6989..33e2a3b 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -1,15 +1,16 @@ - class HostGroupException(Exception): def __init__(self, msg): self.msg = msg def __str__(self): return repr(self.msg) - + + class HostGroupMissingArgumentException(HostGroupException): def __init__(self, missingArgument, hostgroupName): super(HostGroupMissingArgumentException, self).__init__("no " + missingArgument + " defined for Hostgroup " + hostgroupName) + class HostGroup: def __init__(self, name, **kwargs): self.name = name diff --git a/lib/config/parser.py b/lib/config/parser.py index 746358f..9c858ad 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -10,7 +10,7 @@ from members import Member from periods import CronPeriod, DatePeriod, IntervalPeriod from lib.services.service import Service -print id(Service) +#print id(Service) from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task @@ -20,14 +20,13 @@ MOD_PROCESSORS = "processors" MOD_PARSERS = "parsers" MOD_TASKS = "tasks" - - KEY_LAYOUTS = "layouts" KEY_HOSTGROUPS = "hostgroups" KEY_MEMBERS = "members" KEY_PERIODS = "periods" KEY_CORE = "core" + class ConfigurationException(Exception): def __init__(self, msg, log): log.e(msg) @@ -42,15 +41,14 @@ class ConfigParser: """ initializes a new ConfigParser Object - params: - log: pre configured logger Object to post messages while parsing" + :param log: pre configured logger Object to post messages while parsing" """ self.log = log self.hostgroups = {} self.members = {} self.periods = {} self.layouts = {} - self._loadedMods={MOD_SERVICES: {}, MOD_PROCESSORS: {}, MOD_TASKS: {}, MOD_PARSERS: {}} + self._loadedMods = {MOD_SERVICES: {}, MOD_PROCESSORS: {}, MOD_TASKS: {}, MOD_PARSERS: {}} def _create_new_config_dict(self): return {"members": {}, "periods": {}, "hostgroups": {}, "layouts": {}, "core": {}} @@ -64,14 +62,13 @@ class ConfigParser: """ reads the config File and returns a dictionary, while lowering the first keys - params: - configFilename: the path under which the configuration file should be found + :param configFilename: the path under which the configuration file should be found """ if not isfile(configFilename): msg = "config file not found at " + str(configFilename) raise ConfigurationException(msg, self.log) - self.configfilename = configFilename + self.configFilename = configFilename with open(configFilename) as cfgFile: config = cfgFile.read() @@ -102,6 +99,7 @@ class ConfigParser: def _load_module(self, clazz, modPart): """ imports and caches a module. + :param clazz: the filename of the module (i.e email, ping...) :param modPart: the folder of the module. (i.e services, parsers...) :return: the imported/cached module, or throws an error if it couldn't find it @@ -121,6 +119,7 @@ class ConfigParser: """ replaces configuration dicts with their objects by importing and creating it in the first step. In the second step the original list of json config dicts gets replaced by the loaded objects + :param objList: the list of objects which is iterated on :param modPart: the folder from the module (i.e tasks, parsers) :param items_func: function to get a pointer on the list of json-config-objects to replace. Takes one argument and @@ -166,6 +165,7 @@ class ConfigParser: def replace_pointer(self, objectList, replObjectList, id_list_func, id_get_func): """ replaces objects from the config by ids. + :param objectList: the list of objects to be iterated on :param replObjectList: the list of objects to replace :param id_list_func: function taking one argument as object and should return a list of config ids to replace @@ -205,15 +205,14 @@ class FullConfigParser(ConfigParser): def parse_config(self, configFilename): """ parses the json configuration and returns a list of layouts, - which contains all nessesary information of the config file. + which contains all necessary information of the config file. parses the full config Parsing will be done in 3 steps: 1. get raw Config Objects by just passing the values defined inside the config 2. replace references by objects, import services, tasks, parsers and processors 3. do sanity checks - params: - configFilename: indicates which configuration file to parse + :param configFilename: the configuration file to parse """ self.jsonDict = self._read_json_config(configFilename) @@ -230,7 +229,6 @@ class FullConfigParser(ConfigParser): creator = parsePeriodList periods = self._create_raw_Object(self.jsonDict[KEY_PERIODS], "Period", creator) - #2. import and replace items_func = lambda hostgroup: hostgroup.get_services() class_check = lambda service: isinstance(service, Service) @@ -244,7 +242,6 @@ class FullConfigParser(ConfigParser): for hg in hostgroups: services.extend(hg.get_services()) - items_func = lambda service: service.get_parser() class_check = lambda parser: isinstance(parser, Parser) self.replace_with_import(services, MOD_PARSERS, items_func, class_check) @@ -258,7 +255,6 @@ class FullConfigParser(ConfigParser): id_get_func = lambda member: member.id self.replace_pointer(hostgroups, members, id_list_func, id_get_func) - id_list_func = lambda service: service.get_periods() id_get_func = lambda period: period.get_name() self.replace_pointer(services, periods, id_list_func, id_get_func) diff --git a/lib/core/command.py b/lib/core/command.py index 3bd0d88..a9b8f62 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -3,6 +3,7 @@ from subprocess import Popen from subprocess import CalledProcessError from datetime import datetime as dt + class Command: def __init__(self, command, log): self.command = command diff --git a/lib/core/linspector_daemon.py b/lib/core/linspector_daemon.py index 52a7c32..b55ab19 100644 --- a/lib/core/linspector_daemon.py +++ b/lib/core/linspector_daemon.py @@ -13,4 +13,4 @@ class LinspectorDaemon(Daemon): #logger.writeLogToFile(_logfile, str(err)) print "failed" sys.exit(1) - time.sleep(1) + time.sleep(1) \ No newline at end of file diff --git a/lib/core/logger.py b/lib/core/logger.py index 8b5e398..9acc559 100644 --- a/lib/core/logger.py +++ b/lib/core/logger.py @@ -17,7 +17,6 @@ class Logger(): :param logfile: the file where to log. Logs are rotated by default. :param logfileLevel: the LoggingLevel for the file Logger. (DEBUG default) """ - logfile = path.expanduser(logfile) if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) diff --git a/lib/parsers/parser.py b/lib/parsers/parser.py index 335b596..6906df0 100644 --- a/lib/parsers/parser.py +++ b/lib/parsers/parser.py @@ -10,5 +10,4 @@ class Parser: pass def generate_parse_result(self, result): - pass - + pass \ No newline at end of file diff --git a/lib/processors/processor.py b/lib/processors/processor.py index 988f696..c45b363 100644 --- a/lib/processors/processor.py +++ b/lib/processors/processor.py @@ -1,7 +1,5 @@ """ -Created on Jun 16, 2013 - -@author: rafael +The processor class for postprocessing polled data. """ diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index e2d0371..c75e158 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -9,5 +9,6 @@ class Syslog(Processor): def __init__(self): pass + def create(kwargs): - return Syslog(**kwargs) + return Syslog(**kwargs) \ No newline at end of file diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 01db30c..fa7ebbf 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -2,7 +2,7 @@ The email task. """ -from lib.tasks.task import Task +from task import Task class EmailTask(Task): diff --git a/lib/tasks/task.py b/lib/tasks/task.py index 12d2269..a81597e 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -1,7 +1,5 @@ """ -Created on Jun 15, 2013 - -@author: Rafael Timmerberg +The task class. """ @@ -16,8 +14,7 @@ class Task: Be aware! this method can only get called once! - params: - taskType: the type of this task + :param taskType: the type of this task """ if hasattr(self, "_taskType"): raise Exception("taskType is only allowed to set once!") @@ -25,7 +22,7 @@ class Task: def get_task_type(self): """ - returns the type set by set_type_task + :return: the type set by set_type_task """ return self._taskType @@ -36,8 +33,7 @@ class Task: default does nothing - params: - msg: the msg for this task + :param msg: the msg for this task """ pass @@ -47,12 +43,10 @@ class Task: It determines if it has an appropriate type by comparing taskType with get_task_type(). Calls execute_task() if the type matches - params: - taskType: the type of the fail which is compared with get_task_type() - msg: the error message + :param taskType: the type of the fail which is compared with get_task_type() + :param msg: the error message - return: - True if execute_task() is called succesfully, else False + :return: True if execute_task() is called succesfully, else False """ if self.get_task_type() == taskType: self.execute_task(msg) diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index b5cf146..ee407e4 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -18,6 +18,5 @@ class XmppTask(Task): pass - def create(taskDict): return XmppTask(**taskDict) \ No newline at end of file From f53bb771e5b65ae49bb2538d8593439900c36aa2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 03:27:20 +0200 Subject: [PATCH 117/268] docs update From a656ad4b5e9b2df92165df970913b727b6210efd Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 03:47:06 +0200 Subject: [PATCH 118/268] args fix in members and added args to parser classes. --- linspector.json | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/linspector.json b/linspector.json index b1f464e..b0d6794 100644 --- a/linspector.json +++ b/linspector.json @@ -5,7 +5,7 @@ "comment": "The Linspector Admin", "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, - { "class": "xmpp", "type": "critical", "arfixed parsing, replaced non_workin instance_check with gs":{ "rcpt": "admin@jabber.hanez.org" }}] + { "class": "xmpp", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] }, "hanez":{ "name": "Johannes Findeisen", @@ -48,7 +48,8 @@ "fails":{ "warning": "100ms", "critical": "150ms" }, "periods":[ "short" ], "threshold": 10, - "parser":{ "class": "shell", "line": 2, "col": 5 } + "parser":{ "class": "shell", + "args":{ "line": 2, "col": 5 }} }, { "class": "tcpconnect", @@ -75,7 +76,8 @@ "protocol": "https" }, "periods":[ "long" ], "threshold": 2, - "parser":{ "class": "grep", "string": "

I am up!

" }, + "parser":{ "class": "grep", + "args":{ "string": "

I am up!

" }}, "comment": "Just a string grep" } ] @@ -89,7 +91,8 @@ "fails":{ "warning": "100ms", "critical": "150ms" }, "periods":[ "short" ], "threshold": 10, - "parser":{ "class": "shell", "line": 2, "col": 5 } + "parser":{ "class": "shell", + "args":{ "line": 2, "col": 5 }} }, { "class": "tcpconnect", @@ -109,9 +112,12 @@ "fails":{ "warning": "80%", "critical": "90%" }, "periods":[ "long" ], "threshold": 10, - "parser":[{ "class": "grep", "line": "/dev/sda1", "col": 5 }, - [{ "class": "grep", "line": "/dev/sda2", "col": 5 }, - { "class": "grep", "line": "/dev/sda2", "col": 5 }]] + "parser":[{ "class": "grep", + "args":{ "line": "/dev/sda1", "col": 5 }}, + [{ "class": "grep", + "args":{ "line": "/dev/sda2", "col": 5 }}, + { "class": "grep", + "args":{ "line": "/dev/sda2", "col": 5 }}]] }, { "class": "shell", @@ -120,7 +126,8 @@ "fails":{ "warning": 4.00, "critical": 8.00 }, "periods":[ "middle" ], "threshold": 10, - "parser":{ "class": "shell", "line": 1, "col": 4 } + "parser":{ "class": "shell", + "args":{ "line": 1, "col": 4 }} } ] }, @@ -141,7 +148,8 @@ "fails":{ "warning": "100ms", "critical": "150ms", "notes": "HeyHo! A ping failed, wake up! (@response)" }, "periods":[ "short" ], "threshold": 10, - "parser":{ "class": "shell", "line": 2, "col": 8 } + "parser":{ "class": "shell", + "args":{ "line": 2, "col": 8 }} }, { "class": "snmpget", From 1a9b30eba2b9a4c5ab3680ba03f61614b73ebede Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 03:50:30 +0200 Subject: [PATCH 119/268] deleted old stuff --- test/linspector.full.json | 535 ----------------------------------- test/linspector.minimal.json | 76 ----- test/linspector.old.json | 232 --------------- 3 files changed, 843 deletions(-) delete mode 100644 test/linspector.full.json delete mode 100644 test/linspector.minimal.json delete mode 100644 test/linspector.old.json diff --git a/test/linspector.full.json b/test/linspector.full.json deleted file mode 100644 index a79f93c..0000000 --- a/test/linspector.full.json +++ /dev/null @@ -1,535 +0,0 @@ -{ - "services": - { - "discusage": {"command": "ssh @host df -a @device", "parser": "df"}, - "load": {"command": "ssh @host uptime"}, - "dirsize": { "command": "ssh @host du -chs @path"}, - "filesize": {"command": "ssh @host du -chs @path"}, - "loggedinusercount": {"command": "ssh @host who | wc -l"}, - "loggedinusers": {"command": "ssh @host who"}, - "swapusage": {"command": "ssh @host cat /proc/swaps"}, - "processcount": {"command": "ssh @host ps ax | wc -l"}, - "processcountbyname": {"command": "ssh @host ps ax | grep @name | wc -l"}, - "fileage": {"command": "ssh @host ls -l @file"}, - "ping": {"command": "ping @host"}, - "snmpget": {"command": "snmpget -v1 -c public $oid"}, - "busy_waiting": {"command": "sleep 3600"}, - "htmlcontent": {"command": "wget -qO- @url", "comment": "Get HTML Content for a string lookup."} - }, - "filters": - { - "email": - { - "command": "/usr/bin/warn_the_admin_mail @member @+message", - "comment": "Sends an E-Mail to the member.", - "priority": 1 - }, - "sms": - { - "command": "/usr/bin/warn_the_admin_sms @member @+message", - "comment": "Sends a Short Message to the member.", - "priority": 0 - }, - "foo": - { - "command": "/usr/bin/warn_the_admin_foo @member @+message", - "priority": 500 - }, - "mongowriter": - { - "command": "./plugins/mongowriter.py @+message localhost 27017 linspector123", - "priority": 1000 - } - }, - "members": - { - "hanez": - { - "name": "Johannes Findeisen", - "comment": "Just a nerd doing admin stuff...", - "parent": "admin", - "filters": - { - "email": "you@hanez.org", - "sms": "+23345567" - } - }, - "linspector": - { - "name": "Linspector BOT", - "comment": "Botty Botsen...", - "parent": "admin", - "filters": - { - "email": "botty@hanez.org", - "sms": "+23345567213123" - } - }, - "unixpeople": - { - "name": "Hanna Findeisen", - "comment": "Master of UNIX", - "parent": "admin", - "filters": - { - "email": "master@hanez.org", - "sms": "+2334556733333" - } - }, - "admin": - { - "name": "Peter Hansen", - "comment": "The son of Hans-Peter Hansen", - "parent": "ultraadmin", - "filters": - { - "email": "admin@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ultraadmin": - { - "name": "Hans-Peter Hansen (CEO)", - "comment": "The guru of the Datacenter", - "parent": "darthvader", - "filters": - { - "email": "bofh@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "darthvader": - { - "name": "Darth Vader", - "comment": "The Father", - "filters": - { - "email": "darth.vader@systemchaos.org" - } - }, - "jens": - { - "name": "Jens Larssen", - "comment": "Our network guru", - "filters": - { - "email": "jens@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ruff": - { - "name": "Ruffn Buffn", - "filters": - { - "sms": "+23343457" - } - }, - "mongowriter": - { - "name": "MongoDB Database writer plugin", - "filters": - { - "mongowriter": "localhost" - } - } - }, - "periods": - { - "twentyfourseven": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "hour": "*", - "minute": "5", - "second": "", - "comment": "All day all night... every five minutes!" - }, - "twentyfour_weekdays": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "day_of_week": "mon,tue,wed,thu,fri", - "hour": "*", - "minute": "5" - }, - "twentyfour_weekend": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "day_of_week": "5-6", - "hour": "*", - "minute": "15" - }, - "onmonday": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "day_of_week": "mon", - "hour": "*", - "minute": "5" - }, - "onfriday": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "day_of_week": "fri", - "hour": "0-20", - "minute": "5" - }, - "onmondayandfriday": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "day_of_week": "mon,fri", - "hour": "*", - "minute": "5" - }, - "hanezbirthday": - { - "year": "*", - "month": "12", - "day": "6" - }, - "ruffdoesnever": - { - } - }, - "hosts": - { - "hanez": - { - "host": "www.hanez.org", - "services": - { - "discusage": - [ - { "device": "/dev/sda1", "warning": "80%", "critical": "90%" }, - { "device": "/dev/sda2", "warning": "70%", "critical": "90%" }, - { "device": "/dev/sda3", "warning": "70GB", "critical": "90GB" } - ], - "load": - [ - { "warning": 8.00, "critical": 12.00 } - ], - "dirsize": - [ - { "path": "/var/log", "warning": 30000000, "critical": 40000000 } - ], - "processcount": - [ - { "warning": 3000, "critical": 3800 } - ], - "processcountbyname": - [ - { "name": "java", "warning": 100, "critical": 200 } - ], - "fileage": - [ - { "file": "/var/backup/server_1", "warning": 2, "critical": 3 } - ], - "htmlcontent": - [ - { "url": "@host/test.php", "content": "

Server up!

" } - ] - } - }, - "www.unixpeople.org": - { - "host": "23.23.23.23", - "parent": "router.systemchaos.org", - "services": - { - "discusage": - [ - { "device": "/dev/sda1", "warning": "80%", "critical": "90%" } - ], - "load": - [ - { "device": "all", "warning": 8.00, "critical": 12.00 } - ] - } - }, - "www2.unixpeople.org": - { - "host": "23.23.23.24", - "parent": "router.systemchaos.org", - "services": - { - "discusage": - [ - { "device": "/dev/sda1", "warning": "80%", "critical": "90%" } - ], - "load": - [ - { "device": "all", "warning": 8.00, "critical": 12.00 } - ] - } - }, - "www3.unixpeople.org": {"host": "23.23.23.25", "parent": "router.systemchaos.org", - "services": {"discusage":[{ "device": "/dev/sda1", "warning": "80%", "critical": "90%"}], - "load":[{ "device": "all", "warning": 8.00, "critical": 12.00 }], - "ping":[{"warning": "100ms", "critical": "250ms"}] - } - }, - "www.systemchaos.org": - { - "host": "www.systemchaos.org", - "parent": "router.systemchaos.org", - "services": - { - "htmlcontent": - [ - { "url": "@host", "content": "SYSTEMCHAOS" } - ] - } - }, - "devserver": - { - "host": "devserver.systemchaos.org", - "parent": "router.systemchaos.org", - "services": - { - "ping": - [ - { "warning": "100ms", "critical": "250ms" } - ] - } - }, - "www01.linspector.org": {"host": "www01.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www02.linspector.org": {"host": "www02.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www03.linspector.org": {"host": "www03.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www04.linspector.org": {"host": "www04.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www05.linspector.org": {"host": "www05.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www06.linspector.org": {"host": "www06.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www07.linspector.org": {"host": "www07.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www08.linspector.org": {"host": "www08.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www09.linspector.org": {"host": "www09.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www10.linspector.org": {"host": "www10.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www11.linspector.org": {"host": "www11.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www12.linspector.org": {"host": "www12.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www13.linspector.org": {"host": "www13.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www14.linspector.org": {"host": "www14.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www15.linspector.org": {"host": "www15.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www16.linspector.org": {"host": "www16.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www17.linspector.org": {"host": "www17.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www18.linspector.org": {"host": "www18.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www19.linspector.org": {"host": "www19.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www20.linspector.org": {"host": "www20.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www21.linspector.org": {"host": "www21.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "www22.linspector.org": {"host": "www22.linspector.org", "parent": "router.systemchaos.org", - "services": {"ping":[{"warning": "100ms", "critical": "250ms"}]} - }, - "router.systemchaos.org": {"host": "192.168.2.1", - "services":{"ping":[{ "warning": "100ms", "critical": "250ms"}]} - } - }, - "hostgroups": - { - "all": - { - "members": ["admin"], - "hosts": ["hanez", "www.unixpeople.org", "www2.unixpeople.org", "www3.unixpeople.org", - "www.systemchaos.org", "router.systemchaos.org", "www01.linspector.org", "www02.linspector.org", - "www03.linspector.org", "www04.linspector.org", "www05.linspector.org", "www06.linspector.org", - "www07.linspector.org", "www08.linspector.org", "www09.linspector.org", "www10.linspector.org", - "www11.linspector.org", "www12.linspector.org", "www13.linspector.org", "www14.linspector.org", - "www15.linspector.org", "www16.linspector.org", "www17.linspector.org", "www18.linspector.org", - "www19.linspector.org", "www20.linspector.org", "www21.linspector.org", "www22.linspector.org"], - "parent": "network", - "threshold": 10, - "services": - { - "load": ["twentyfourseven"], - "discusage":["twentyfourseven"], - "ping": ["twentyfourseven"] - } - }, - "all_for_hanez": - { - "members": ["hanez"], - "hosts": ["hanez", "www.unixpeople.org", "www2.unixpeople.org", "www3.unixpeople.org", - "www.systemchaos.org", "router.systemchaos.org", "www01.linspector.org", "www02.linspector.org", - "www03.linspector.org", "www04.linspector.org", "www05.linspector.org", "www06.linspector.org", - "www07.linspector.org", "www08.linspector.org", "www09.linspector.org", "www10.linspector.org", - "www11.linspector.org", "www12.linspector.org", "www13.linspector.org", "www14.linspector.org", - "www15.linspector.org", "www16.linspector.org", "www17.linspector.org", "www18.linspector.org", - "www19.linspector.org", "www20.linspector.org", "www21.linspector.org", "www22.linspector.org"], - "parent": "network", - "threshold": 10, - "services": - { - "load": ["twentyfourseven"], - "discusage":["twentyfourseven"], - "ping": ["twentyfourseven"] - } - }, - "all_for_nonexistent": - { - "members": ["nonexistent"], - "hosts": ["hanez", "www.unixpeople.org", "www2.unixpeople.org", "www3.unixpeople.org", - "www.systemchaos.org", "router.systemchaos.org", "www01.linspector.org", "www02.linspector.org", - "www03.linspector.org", "www04.linspector.org", "www05.linspector.org", "www06.linspector.org", - "www07.linspector.org", "www08.linspector.org", "www09.linspector.org", "www10.linspector.org", - "www11.linspector.org", "www12.linspector.org", "www13.linspector.org", "www14.linspector.org", - "www15.linspector.org", "www16.linspector.org", "www17.linspector.org", "www18.linspector.org", - "www19.linspector.org", "www20.linspector.org", "www21.linspector.org", "www22.linspector.org"], - "parent": "network", - "threshold": 10, - "services": - { - "load": ["nix"], - "discusage":["nix"], - "ping": ["nix"] - } - }, - "hanez": - { - "members": ["hanez", "jens"], - "hosts": ["hanez", "router.systemchaos.org", "www.unixpeople.org", "www2.unixpeople.org", - "www3.unixpeople.org"], - "parent": "network", - "threshold": 5, - "services": - { - "load": ["hanezbirthday"], - "discusage": ["onmondayandfriday"], - "ping": ["onmondayandfriday"] - } - }, - "unixpeople": - { - "members": ["unixpeople", "admin", "hanez", "nobody"], - "hosts": ["www.unixpeople.org", "www2.unixpeople.org", "www3.unixpeople.org", "www08.linspector.org"], - "parent": "network", - "threshold": 5, - "services": - { - "load": ["onmondayandfriday"], - "discusage": ["onmondayandfriday"], - "ping": ["twentyfourseven"] - } - }, - "linspector-01": - { - "members": ["linspector", "hanez", "nobody"], - "hosts": ["www01.linspector.org", "www02.linspector.org", "www03.linspector.org", "www04.linspector.org", - "www05.linspector.org", "www06.linspector.org", "www07.linspector.org", "www08.linspector.org"], - "parent": "network", - "threshold": 5, - "services": - { - "load": ["twentyfourseven"], - "discusage": ["twentyfourseven"], - "ping": ["twentyfourseven"] - } - }, - "linspector-02": - { - "members": ["linspector", "hanez", "nobody"], - "hosts": ["www09.linspector.org", "www10.linspector.org", "www11.linspector.org", "www12.linspector.org", - "www13.linspector.org", "www14.linspector.org", "www15.linspector.org", "www16.linspector.org"], - "parent": "network", - "threshold": 5, - "services": - { - "load": ["twentyfourseven"], - "discusage": ["twentyfourseven"], - "ping": ["twentyfourseven"] - } - }, - "devserver": - { - "members": ["devs", "hanez"], - "hosts": ["dev.hanez.org"], - "parent": "network", - "threshold": 5, - "services": - { - "load": ["twentyfourseven"], - "discusage": ["twentyfourseven"], - "ping": ["twentyfourseven"] - } - }, - "network": - { - "members": ["jens"], - "hosts": ["router.systemchaos.org"], - "threshold": 5, - "services": - { - "load": ["onmondayandfriday"], - "ping": ["twentyfourseven"] - } - }, - "ruff": - { - "members": ["ruff", "hanez"], - "hosts": ["www.fuff.org", "www.unixpeople.org"], - "threshold": 100, - "services": - { - "busy_waiting": ["ruffdoesnever"] - } - } - }, - "layouts": {"production": {"hostgroups": ["all", "hanez", "network"], "enabled": true}, - "lazy": {"hostgroups": ["hanez", "ruff"], "enabled": false}} -} diff --git a/test/linspector.minimal.json b/test/linspector.minimal.json deleted file mode 100644 index 878a619..0000000 --- a/test/linspector.minimal.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "services": {"ping": {"command": "ping -c 1 @host"}, - "tcpconnect": {"command": "tcpconnect @host @port"}}, - "filters": - { - "email": - { - "command": "email @member @+message", - "comment": "Sends an E-Mail to the member.", - "priority": 1 - } - }, - "members": - { - "hanez": - { - "name": "Johannes Findeisen", - "comment": "Just a nerd doing admin stuff...", - "filters": {"email": "you@hanez.org"} - } - }, - "periods": {"shortPeriod": {"seconds": 5, "comment": "Interval job; every 10 seconds"}}, - "hosts": - { - "a.systemchaos.org": {"host": "a.systemchaos.org", - "services": { - "ping":[{ "args": { "device": "/dev/sda1" }, - "fails": { "warning": "100ms", "critical": "150ms" }, - "parser": { "name": "ping", "line": 2, "col": 5 }}] - } - }, - "b.systemchaos.org": {"host": "b.systemchaos.org", "services": {"ping":[{}]}}, - "google.de": {"host": "google.de", "services": {"ping":[{}]}}, - "foobar.systemchaos.org": {"host": "foobar.systemchaos.org", - "services": { - "tcpconnect":[{ "args": { "port": 80 }, - "fails": { }, - "threshold": 2, - "parser": { "name": "none" }}] - } - }, - "snmp.systemchaos.org": {"host": "snmp.systemchaos.org", - "services": { - "snmpget":[{ "args": { "port": 5555, "oid": "1.3.6.1.4.1.2681.1.2.102." }, - "fails": { "warning": "8", "critical": "16" }, - "parser": { "name": "snmpget" }, - "comment": "Value X from Y"}] - } - }, - "web.systemchaos.org": {"host": "web.systemchaos.org", - "services": { - "htmlcontent":[{ "args": { "port": 80, "path": "/status.cgi", "string": "

I am up!

" }, - "fails": { }, - "threshold": 2, - "parser": { "name": "none" }, - "comment": "Just a string grep"}] - } - } - }, - "hostgroups": - { - "all": - { - "members": ["hanez"], - "hosts": ["a.systemchaos.org", "b.systemchaos.org", "google.de"], - "threshold": 10, - "services": {"ping": ["shortPeriod"]} - } - }, - "layouts": {"production": {"hostgroups": ["all"], "enabled": true} - }, - "core": { - "max_logfile_size": 1024000, - "max_logfile_count": 4 - } -} diff --git a/test/linspector.old.json b/test/linspector.old.json deleted file mode 100644 index 82ceb0c..0000000 --- a/test/linspector.old.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "services": - { - "discusage": {"command": "ssh @host df -a @device", "parser": "df"}, - "load": {"command": "ssh @host uptime"}, - "dirsize": { "command": "ssh @host du -chs @path"}, - "filesize": {"command": "ssh @host du -chs @path"}, - "loggedinusercount": {"command": "ssh @host who | wc -l"}, - "loggedinusers": {"command": "ssh @host who"}, - "swapusage": {"command": "ssh @host cat /proc/swaps"}, - "processcount": {"command": "ssh @host ps ax | wc -l"}, - "processcountbyname": {"command": "ssh @host ps ax | grep @name | wc -l"}, - "fileage": {"command": "ssh @host ls -l @file"}, - "ping": {"command": "ping @host"}, - "snmpget": {"command": "snmpget -v1 -c public $oid"}, - "busy_waiting": {"command": "sleep 3600"}, - "htmlcontent": {"command": "wget -qO- @url", "comment": "Get HTML Content for a string lookup."} - }, - "filters": - { - "email": - { - "command": "/usr/bin/warn_the_admin_mail @member @+message", - "comment": "Sends an E-Mail to the member.", - "priority": 1 - }, - "sms": - { - "command": "/usr/bin/warn_the_admin_sms @member @+message", - "comment": "Sends a Short Message to the member.", - "priority": 0 - }, - "foo": - { - "command": "/usr/bin/warn_the_admin_foo @member @+message", - "priority": 500 - }, - "mongowriter": - { - "command": "./plugins/mongowriter.py @+message localhost 27017 linspector123", - "priority": 1000 - } - }, - "members": - { - "hanez": - { - "name": "Johannes Findeisen", - "comment": "Just a nerd doing admin stuff...", - "parent": "admin", - "filters": - { - "email": "you@hanez.org", - "sms": "+23345567" - } - }, - "linspector": - { - "name": "Linspector BOT", - "comment": "Botty Botsen...", - "parent": "admin", - "filters": - { - "email": "botty@hanez.org", - "sms": "+23345567213123" - } - }, - "unixpeople": - { - "name": "Hanna Findeisen", - "comment": "Master of UNIX", - "parent": "admin", - "filters": - { - "email": "master@hanez.org", - "sms": "+2334556733333" - } - }, - "admin": - { - "name": "Peter Hansen", - "comment": "The son of Hans-Peter Hansen", - "parent": "ultraadmin", - "filters": - { - "email": "admin@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ultraadmin": - { - "name": "Hans-Peter Hansen (CEO)", - "comment": "The guru of the Datacenter", - "parent": "darthvader", - "filters": - { - "email": "bofh@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "darthvader": - { - "name": "Darth Vader", - "comment": "The Father", - "filters": - { - "email": "darth.vader@systemchaos.org" - } - }, - "jens": - { - "name": "Jens Larssen", - "comment": "Our network guru", - "filters": - { - "email": "jens@systemchaos.org", - "sms": "+23345567", - "phone": "+435345345" - } - }, - "ruff": - { - "name": "Ruffn Buffn", - "filters": - { - "sms": "+23343457" - } - }, - "mongowriter": - { - "name": "MongoDB Database writer plugin", - "filters": - { - "mongowriter": "localhost" - } - } - }, - "periods": - { - "twentyfourseven": - { - "year": "*", - "month": "*", - "day": "*", - "week": "*", - "hour": "*", - "minute": "*/1", - "second": "0", - "comment": "Cron Job / Every minute" - }, - "do_every_x_times" : { - "days": 0, - "weeks": 0, - "hours": 0, - "minutes": 0, - "seconds": 10, - "comment": "Interval Job / Every 10 seconds" - }, - "next_christmas" : { - "date": "2013-12-24 20:00:00", - "comment": "Date Job / Just one day" - } - }, - "hosts": - { - "hanez": - { - "host": "www.hanez.org", - "services": - { - "discusage": - [ - { "device": "/dev/sda1", "warning": "80%", "critical": "90%" }, - { "device": "/dev/sda2", "warning": "70%", "critical": "90%" }, - { "device": "/dev/sda3", "warning": "70GB", "critical": "90GB" } - ], - "load": - [ - { "warning": 8.00, "critical": 12.00 } - ], - "dirsize": - [ - { "path": "/var/log", "warning": 30000000, "critical": 40000000 } - ], - "processcount": - [ - { "warning": 3000, "critical": 3800 } - ], - "processcountbyname": - [ - { "name": "java", "warning": 100, "critical": 200 } - ], - "fileage": - [ - { "file": "/var/backup/server_1", "warning": 2, "critical": 3 } - ], - "htmlcontent": - [ - { "url": "@host/test.php", "content": "

Server up!

" } - ], - "ping": - [ - {} - ] - } - } - }, - "hostgroups": - { - "all": - { - "members": ["admin"], - "hosts": ["hanez"], - "parent": "network", - "threshold": 10, - "services": - { - "ping": ["do_every_x_times"] - } - } - }, - "layouts": {"production": {"hostgroups": ["all", "hanez", "network"], "enabled": true}, - "lazy": {"hostgroups": ["hanez", "ruff"], "enabled": false} - }, - "core": { - "max_logfile_size": 1024000, - "max_logfile_count": 4, - "max_worker_threads": 8 - } -} From 66ab7b6d9cb9117a3a7f09ce27077498b55ecc17 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 04:45:23 +0200 Subject: [PATCH 120/268] added some args stuff, added dummy shell parser, renamed classes in processors... --- lib/parsers/shell.py | 6 ++++++ lib/processors/mariadb.py | 14 ++++++++++++++ lib/processors/mongodb.py | 4 ++-- lib/processors/syslog.py | 4 ++-- linspector.json | 4 ++++ 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 lib/parsers/shell.py create mode 100644 lib/processors/mariadb.py diff --git a/lib/parsers/shell.py b/lib/parsers/shell.py new file mode 100644 index 0000000..15d5bf9 --- /dev/null +++ b/lib/parsers/shell.py @@ -0,0 +1,6 @@ +from parser import Parser + + +class ShellParser(Parser): + def __init__(self): + pass \ No newline at end of file diff --git a/lib/processors/mariadb.py b/lib/processors/mariadb.py new file mode 100644 index 0000000..f8094ec --- /dev/null +++ b/lib/processors/mariadb.py @@ -0,0 +1,14 @@ +""" +The MariaDB processor +""" + +from processor import Processor + + +class MariadbProcessor(Processor): + def __init__(self): + pass + + +def create(kwargs): + return MariadbProcessor(**kwargs) \ No newline at end of file diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index c94c84c..8b9d579 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -5,10 +5,10 @@ The MongoDB processor from processor import Processor -class Mongodb(Processor): +class MongodbProcessor(Processor): def __init__(self): pass def create(kwargs): - return Mongodb(**kwargs) \ No newline at end of file + return MongodbProcessor(**kwargs) \ No newline at end of file diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index c75e158..645b488 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -5,10 +5,10 @@ The syslog processor from processor import Processor -class Syslog(Processor): +class SyslogProcessor(Processor): def __init__(self): pass def create(kwargs): - return Syslog(**kwargs) \ No newline at end of file + return SyslogProcessor(**kwargs) \ No newline at end of file diff --git a/linspector.json b/linspector.json index b0d6794..aae9209 100644 --- a/linspector.json +++ b/linspector.json @@ -40,6 +40,10 @@ { "class": "syslog", "args":{ "host": "syslog.linspector.org", "user": "syslog", "password": "secret" } + }, + { + "class": "mariadb", + "args":{ "host": "mariadb.linspector.org", "port": "3306", "user": "maria", "password": "secret", "database": "linspector" } } ], "services":[ From bbe79a76a31168ce8f324a8f135a9b33b29484aa Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 04:47:28 +0200 Subject: [PATCH 121/268] added create method to shell parser --- lib/parsers/shell.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/parsers/shell.py b/lib/parsers/shell.py index 15d5bf9..78fde57 100644 --- a/lib/parsers/shell.py +++ b/lib/parsers/shell.py @@ -3,4 +3,8 @@ from parser import Parser class ShellParser(Parser): def __init__(self): - pass \ No newline at end of file + pass + + +def create(kwargs): + return ShellParser(**kwargs) \ No newline at end of file From 8e53382e70025b4b2a20d3dffffe89ecd8e48ded Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 05:14:47 +0200 Subject: [PATCH 122/268] small fix in tcpconnect service --- lib/services/tcpconnect.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 3fcf151..c30cd46 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -6,7 +6,6 @@ not use a parser. """ import socket -from lib.config.services import Service from service import Service From fca615e8d939d7eb5213ba0f99a0417cebda7b06 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 23:04:13 +0200 Subject: [PATCH 123/268] fixed class_check behavior, added minimal.json --- lib/config/parser.py | 34 ++++++++++-------------------- lib/services/http.py | 2 +- lib/services/ping.py | 2 +- lib/services/shell.py | 2 +- lib/services/snmpget.py | 2 +- lib/services/ssh.py | 2 +- lib/services/tcpconnect.py | 2 +- linspector | 2 +- minimal.json | 42 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 60 insertions(+), 30 deletions(-) create mode 100644 minimal.json diff --git a/lib/config/parser.py b/lib/config/parser.py index 9c858ad..93a37ac 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -108,10 +108,9 @@ class ConfigParser: if clazz in mods: return mods["class"] else: - mod = __import__(clazz) - #path = join(getcwd(), "lib", modPart, clazz + ".py") - #self.log.w(path) - #mod = imp.load_source(clazz, path) + #mod = __import__(clazz) + path = join("lib", modPart, clazz + ".py") + mod = imp.load_source(clazz, path) mods[clazz] = mod return mod @@ -123,6 +122,7 @@ class ConfigParser: :param objList: the list of objects which is iterated on :param modPart: the folder from the module (i.e tasks, parsers) :param items_func: function to get a pointer on the list of json-config-objects to replace. Takes one argument and + should return a list of :param class_check: currently unsupported """ for obj in objList: @@ -130,25 +130,15 @@ class ConfigParser: items = items_func(obj) for clazzItem in items: try: - if "class" not in clazzItem: - self.log.w("python says class is not in class item!") - self.log.w(modPart) - self.log.w(clazzItem) - self.log.w(clazzItem["class"]) clazz = clazzItem["class"] - path = "lib/" + modPart - sys.path.append(path) mod = self._load_module(clazz, modPart) item = mod.create(clazzItem) - repl.append(item) - #TODO: activate the crappy classcheck if answer is provided - #http://stackoverflow.com/questions/17179440/ - self.log.d("warning: instance_check isn't working yet! TRUST_ALL = TRUE") - #if class_check(item): - # repl.append(item) - #else: - # self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + if class_check(item): + repl.append(item) + else: + self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + except ImportError, err: self.log.w("could not import " + clazz + ": " + str(clazzItem) + "! reason") self.log.w(str(err)) @@ -156,9 +146,7 @@ class ConfigParser: self.log.w("Key " + str(k) + " not in classItem " + str(clazzItem)) except Exception, e: self.log.w("Error while replacing class ( " + clazz + " ):" + str(e)) - finally: - if path in sys.path: - del sys.path[sys.path.index(path)] + del items[:] items.extend(repl) @@ -191,7 +179,7 @@ def parsePeriodList(name, values): return DatePeriod(name, **values) comp = ["weeks", "days", "hours", "minutes", "seconds", "start_date"] - if len([i for i in comp if i in values]) > 0 : + if len([i for i in comp if i in values]) > 0: return IntervalPeriod(name, **values) comp = ["year", "month", "day", "week", "day_of_week", "hour", "minute", "second"] diff --git a/lib/services/http.py b/lib/services/http.py index a23c42b..254bb4b 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -9,7 +9,7 @@ to just report this code and not use a parser. """ import urllib -from service import Service +from lib.services.service import Service class HttpService(Service): diff --git a/lib/services/ping.py b/lib/services/ping.py index 69d7f31..33668f8 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -3,7 +3,7 @@ The ping service in pure Python. """ # http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ -from service import Service +from lib.services.service import Service class PingService(Service): diff --git a/lib/services/shell.py b/lib/services/shell.py index a1ebc32..65878fb 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -2,7 +2,7 @@ The shell service. This is for executing local shell commands and retrieve the output. """ -from service import Service +from lib.services.service import Service class ShellService(Service): diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index 15a0d7c..f59b7d2 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -3,7 +3,7 @@ The snmpget service in pure Python. """ #from pysnmp.entity.rfc3413.oneliner import cmdgen -from service import Service +from lib.services.service import Service class SnmpgetService(Service): diff --git a/lib/services/ssh.py b/lib/services/ssh.py index 44116a1..7bc083e 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -7,7 +7,7 @@ This service is using paramiko (http://www.lag.net/paramiko/). import paramiko import pprint import os -from service import Service +from lib.services.service import Service class SshService(Service): diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index c30cd46..358fcfa 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -6,7 +6,7 @@ not use a parser. """ import socket -from service import Service +from lib.services.service import Service class TcpconnectService(Service): diff --git a/linspector b/linspector index dbbfb89..c1f7f50 100755 --- a/linspector +++ b/linspector @@ -1,7 +1,7 @@ #!/usr/bin/python2.7 -tt __version__ = "0.4/TETRIS" -__default_config__ = "./linspector.json" +__default_config__ = "./minimal.json" import argparse import time diff --git a/minimal.json b/minimal.json new file mode 100644 index 0000000..1c459bc --- /dev/null +++ b/minimal.json @@ -0,0 +1,42 @@ +{ + "members":{ + "homer":{ + "name": "Homer Simpson", + "comment": "Security Inspector", + "tasks": [{"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}] + } + }, + "periods": { + "doh": {"seconds": 10, "comment": "OMG, this means work"}, + "moes_time": {"minute":"0", "hour": "12", "day_of_week": "4", "comment": "much better"}, + "marges_birthday": { "date": "1965-2-24 04:00:00"} + }, + "hostgroups":{ + "power_plant":{ + "members": ["homer"], + "hosts": ["powerplant.springfield.com"], + "processors":[ + {"class": "mongodb", "args":{ "host": "mongodb.burnscorp.org", "user": "homer", "password": "useless", "database": "default" }} + ], + "services":[ + { + "class": "ping", + "fails": {"donut": 2000}, + "periods":["doh"], + "threshold": 500 + }, + { + "class": "tcpconnect", + "args": {"port": 23232}, + "periods": ["moes_time", "marges_birthday"], + "threshold": 0, + "comment": "my personal reminder, hehe" + } + ] + } + }, + "layouts":{ + "main":{"hostgroups": ["power_plant"], "enabled": true} + } + +} \ No newline at end of file From 606edc99b3f43ceec5378ca34b9bde74a207d56b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 23:09:57 +0200 Subject: [PATCH 124/268] fixed relative imports --- lib/parsers/shell.py | 2 +- lib/processors/mariadb.py | 2 +- lib/processors/mongodb.py | 2 +- lib/processors/syslog.py | 2 +- lib/tasks/email.py | 2 +- lib/tasks/sms.py | 2 +- lib/tasks/xmpp.py | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/parsers/shell.py b/lib/parsers/shell.py index 78fde57..9e44bbe 100644 --- a/lib/parsers/shell.py +++ b/lib/parsers/shell.py @@ -1,4 +1,4 @@ -from parser import Parser +from lib.parsers.parser import Parser class ShellParser(Parser): diff --git a/lib/processors/mariadb.py b/lib/processors/mariadb.py index f8094ec..3cc83c3 100644 --- a/lib/processors/mariadb.py +++ b/lib/processors/mariadb.py @@ -2,7 +2,7 @@ The MariaDB processor """ -from processor import Processor +from lib.processors.processor import Processor class MariadbProcessor(Processor): diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 8b9d579..e159ff6 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -2,7 +2,7 @@ The MongoDB processor """ -from processor import Processor +from lib.processors.processor import Processor class MongodbProcessor(Processor): diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index 645b488..5dd8d8a 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -2,7 +2,7 @@ The syslog processor """ -from processor import Processor +from lib.processors.processor import Processor class SyslogProcessor(Processor): diff --git a/lib/tasks/email.py b/lib/tasks/email.py index fa7ebbf..4e0bf39 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -2,7 +2,7 @@ The email task. """ -from task import Task +from lib.tasks.task import Task class EmailTask(Task): diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 49dd80e..3a45dfd 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -2,7 +2,7 @@ The sms task. """ -from task import Task +from lib.tasks.task import Task class SmsTask(Task): diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py index ee407e4..91073ad 100644 --- a/lib/tasks/xmpp.py +++ b/lib/tasks/xmpp.py @@ -2,7 +2,7 @@ The xmpp task. """ -from task import Task +from lib.tasks.task import Task class XmppTask(Task): From d66ed9413d40e8966aefaa1a7974cb17f8941beb Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 23:35:30 +0200 Subject: [PATCH 125/268] finally, minimal config is working :) --- lib/config/members.py | 7 +++++-- lib/config/parser.py | 2 +- lib/parsers/parser.py | 2 +- lib/parsers/shell.py | 2 +- lib/processors/mariadb.py | 2 +- lib/processors/mongodb.py | 2 +- lib/processors/processor.py | 2 +- lib/processors/syslog.py | 2 +- lib/services/http.py | 2 +- lib/services/snmpget.py | 2 +- 10 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/config/members.py b/lib/config/members.py index 33f193d..1491e78 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -3,14 +3,17 @@ import re class Member: def __init__(self, nameid, name="", phone="", comment="", parent="", tasks=None): - self.id = id + self.id = nameid self.name = name self.phone = phone self.tasks = [] self.add_task(tasks) self.comment = comment self.parent = parent - + + def get_id(self): + return self.id + def add_task(self, task): if task is None: return diff --git a/lib/config/parser.py b/lib/config/parser.py index 93a37ac..a16205b 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -240,7 +240,7 @@ class FullConfigParser(ConfigParser): #replace object pointer id_list_func = lambda hostgroup: hostgroup.get_members() - id_get_func = lambda member: member.id + id_get_func = lambda member: member.get_id() self.replace_pointer(hostgroups, members, id_list_func, id_get_func) id_list_func = lambda service: service.get_periods() diff --git a/lib/parsers/parser.py b/lib/parsers/parser.py index 6906df0..8ba3028 100644 --- a/lib/parsers/parser.py +++ b/lib/parsers/parser.py @@ -1,5 +1,5 @@ class Parser: - def __init__(self): + def __init__(self, **kwargs): pass def parse_data(self, data): diff --git a/lib/parsers/shell.py b/lib/parsers/shell.py index 9e44bbe..c767cb3 100644 --- a/lib/parsers/shell.py +++ b/lib/parsers/shell.py @@ -2,7 +2,7 @@ from lib.parsers.parser import Parser class ShellParser(Parser): - def __init__(self): + def __init__(self, **kwargs): pass diff --git a/lib/processors/mariadb.py b/lib/processors/mariadb.py index 3cc83c3..d077d5b 100644 --- a/lib/processors/mariadb.py +++ b/lib/processors/mariadb.py @@ -6,7 +6,7 @@ from lib.processors.processor import Processor class MariadbProcessor(Processor): - def __init__(self): + def __init__(self, **kwargs): pass diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index e159ff6..5c521f5 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -6,7 +6,7 @@ from lib.processors.processor import Processor class MongodbProcessor(Processor): - def __init__(self): + def __init__(self, **kwargs): pass diff --git a/lib/processors/processor.py b/lib/processors/processor.py index c45b363..08d5c88 100644 --- a/lib/processors/processor.py +++ b/lib/processors/processor.py @@ -4,5 +4,5 @@ The processor class for postprocessing polled data. class Processor: - def __init__(self): + def __init__(self, **kwargs): pass \ No newline at end of file diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index 5dd8d8a..84897fa 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -6,7 +6,7 @@ from lib.processors.processor import Processor class SyslogProcessor(Processor): - def __init__(self): + def __init__(self, **kwargs): pass diff --git a/lib/services/http.py b/lib/services/http.py index 254bb4b..6e8dfda 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -51,5 +51,5 @@ class HttpService(Service): #print f.read() -def create(**kwargs): +def create(kwargs): return HttpService(**kwargs) \ No newline at end of file diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index f59b7d2..ec07b3f 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -52,5 +52,5 @@ class SnmpgetService(Service): # print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) -def create(kargs): +def create(kwargs): return SnmpgetService(**kwargs) \ No newline at end of file From 88e63fbfe19b8cf1293d45871fdf3a9fc4c52a10 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 19 Jun 2013 23:48:19 +0200 Subject: [PATCH 126/268] added pointer for hostgroup in service --- lib/config/parser.py | 4 ++++ lib/config/services.py | 4 ++++ lib/services/ping.py | 2 +- lib/services/service.py | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index a16205b..d2b9da7 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -251,4 +251,8 @@ class FullConfigParser(ConfigParser): id_get_func = lambda hostgroup: hostgroup.get_name() self.replace_pointer(layouts, hostgroups, id_list_func, id_get_func) + for hg in hostgroups: + for service in hg.get_services(): + service.set_hostgroup(hg) + return layouts \ No newline at end of file diff --git a/lib/config/services.py b/lib/config/services.py index 143c22d..9232a5a 100644 --- a/lib/config/services.py +++ b/lib/config/services.py @@ -4,6 +4,10 @@ class Service: self.command = command self.comment = comment self.parser = parser + self.hostgroup = None + + def set_hostgroup(self, hostgroup): + self.hostgroup = hostgroup def __str__(self): return "Service('Name: " + self.name + "', 'Command: " + self.command + ", 'Parser: " + self.parser + "')" diff --git a/lib/services/ping.py b/lib/services/ping.py index 33668f8..5553e09 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -8,7 +8,7 @@ from lib.services.service import Service class PingService(Service): def __init__(self, **kwargs): - Service.__init__(self, **kwargs) + super(PingService, self).__init__(**kwargs) def create(kwargs): diff --git a/lib/services/service.py b/lib/services/service.py index f77fef1..9ae770f 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -57,6 +57,12 @@ class Service(object): self._periods.extend(period) else: self._periods.append(period) + + def set_hostgroup(self, hostgroup): + self.hostgroup = hostgroup + + def get_hostgroup(self): + return self.hostgroup def get_periods(self): return self._periods From c2c89fabdfb51bd06270627349b71630520c55e6 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 19 Jun 2013 23:55:56 +0200 Subject: [PATCH 127/268] some deletions --- lib/config/hosts.py | 118 ----------------------------------------- lib/config/services.py | 20 ------- lib/config/tasks.py | 16 ------ 3 files changed, 154 deletions(-) delete mode 100644 lib/config/hosts.py delete mode 100644 lib/config/services.py delete mode 100644 lib/config/tasks.py diff --git a/lib/config/hosts.py b/lib/config/hosts.py deleted file mode 100644 index f507b1a..0000000 --- a/lib/config/hosts.py +++ /dev/null @@ -1,118 +0,0 @@ -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 getHostServiceByName(self, serviceName): - for hostService in self.services: - if serviceName == hostService.service.name: - return hostService - return None - - 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 = "HostService : " + 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, log): - """ - parse the HostList and replace any command as necessary - """ - #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: - log.w("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: - log.d("replacing host in " + hostService.getCommand()) - comm = re.sub('@host', host.host, hostService.getCommand()) - hostService.setCommand(comm) - log.d("new Command: " +comm) - log.d("set in hostService: " + str(hostService)) - replacements.remove('host') - #replacements should be empty now. - #If not we cannot use this command as some values are missing - if len(replacements) > 0: - log.w("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: - log.w("Service " + servicename + " not defined in host " + host.name) - #replace host.service member by parsed HostService Objects - host.services = hostServices - return parsedHosts \ No newline at end of file diff --git a/lib/config/services.py b/lib/config/services.py deleted file mode 100644 index 9232a5a..0000000 --- a/lib/config/services.py +++ /dev/null @@ -1,20 +0,0 @@ -class Service: - def __init__(self, name="", command="", comment="", parser=""): - self.name = name - self.command = command - self.comment = comment - self.parser = parser - self.hostgroup = None - - def set_hostgroup(self, hostgroup): - self.hostgroup = hostgroup - - 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()] diff --git a/lib/config/tasks.py b/lib/config/tasks.py deleted file mode 100644 index 1907563..0000000 --- a/lib/config/tasks.py +++ /dev/null @@ -1,16 +0,0 @@ -class Task: - def __init__(self, name="", command="", priority=0, comment=""): - self.name = name - self.command = command - self.priority = priority - self.comment = comment - - def __str__(self): - return "Task('Name: " + self.name + "', 'Command: " + self.command + "', 'Priority: " + str(self.priority) + "')" - - def clone(self): - return Task(self.name, self.command, self.priority, self.comment) - - -def parseTaskList(tasks): - return [Task(name, **values) for name, values in tasks.items()] \ No newline at end of file From f36df89dd0e645772975e8a29b17f71d2326840c Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 00:26:07 +0200 Subject: [PATCH 128/268] added pointer for hostgroup in service --- lib/config/parser.py | 5 ++++- linspector | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index d2b9da7..7af45b1 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -254,5 +254,8 @@ class FullConfigParser(ConfigParser): for hg in hostgroups: for service in hg.get_services(): service.set_hostgroup(hg) + core = None + if "core" in self.jsonDict: + core = self.jsonDict["core"] - return layouts \ No newline at end of file + return (layouts, core) \ No newline at end of file diff --git a/linspector b/linspector index c1f7f50..4aea47f 100755 --- a/linspector +++ b/linspector @@ -12,6 +12,7 @@ from lib.core.logger import Logger from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler +log = None def parseArgs(): parser = argparse.ArgumentParser( @@ -43,7 +44,7 @@ def parseArgs(): def handleJob(jobInfo): - jobInfo.handleCall() + log.w(jobInfo) def main(): @@ -54,11 +55,20 @@ def main(): if args.action == "start": configParser = FullConfigParser(log) - config = configParser.parse_config(args.config) + layouts, core = configParser.parse_config(args.config) - #jobs = [] - #scheduler = Scheduler() - #scheduler.start() + scheduler = Scheduler() + + + jobs = [] + for layout in layouts: + if layout.is_enabled(): + for hg in layout.get_hostgroups(): + for services in hg.get_services(): + for service in services: + for period in service.get_periods(): + jobs.append(period.createJob(scheduler, service, handleJob)) + scheduler.start() #log.i("starting linspector: reading config... (" + args.config + ")") #config_parser = ConfigParser(log) From d62d79753ed09bedfe0ef74aa86469b1ad55f162 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 00:40:34 +0200 Subject: [PATCH 129/268] dinkey code to debug --- lib/config/hostgroups.py | 4 ++-- linspector | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 33e2a3b..8719f88 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -27,7 +27,7 @@ class HostGroup: self.add_hosts(kwargs[tmp]) tmp = "services" - self.services = [] + self._services = [] if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) self.add_services(kwargs[tmp]) @@ -80,7 +80,7 @@ class HostGroup: return self.processors def get_services(self): - return self.services + return self._services def get_hosts(self): return self.hosts diff --git a/linspector b/linspector index 4aea47f..b245f2f 100755 --- a/linspector +++ b/linspector @@ -64,10 +64,12 @@ def main(): for layout in layouts: if layout.is_enabled(): for hg in layout.get_hostgroups(): - for services in hg.get_services(): - for service in services: - for period in service.get_periods(): - jobs.append(period.createJob(scheduler, service, handleJob)) + for sr in hg.get_services(): + if not isinstance(sr, list): + sr = sr.get_hostgroup().get_services() + for s in sr: + for period in s.get_periods(): + jobs.append(period.createJob(scheduler, s, handleJob)) scheduler.start() #log.i("starting linspector: reading config... (" + args.config + ")") From ab69f45c1255055ff521888dd7690cf4856d0601 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 01:05:09 +0200 Subject: [PATCH 130/268] even more dummy code, python fools me!!! --- lib/config/parser.py | 14 +++++++------- linspector | 11 +++++++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 7af45b1..b5fd4d3 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -212,7 +212,7 @@ class FullConfigParser(ConfigParser): members = self._create_raw_Object(self.jsonDict[KEY_MEMBERS], "Member", creator) creator = lambda name, values: HostGroup(name, **values) - hostgroups = self._create_raw_Object(self.jsonDict[KEY_HOSTGROUPS], "Hostgroup", creator) + self.hostgroups = self._create_raw_Object(self.jsonDict[KEY_HOSTGROUPS], "Hostgroup", creator) creator = parsePeriodList periods = self._create_raw_Object(self.jsonDict[KEY_PERIODS], "Period", creator) @@ -220,14 +220,14 @@ class FullConfigParser(ConfigParser): #2. import and replace items_func = lambda hostgroup: hostgroup.get_services() class_check = lambda service: isinstance(service, Service) - self.replace_with_import(hostgroups, MOD_SERVICES, items_func, class_check) + self.replace_with_import(self.hostgroups, MOD_SERVICES, items_func, class_check) items_func = lambda hostgroup: hostgroup.get_processors() class_check = lambda processor: isinstance(processor, Processor) - self.replace_with_import(hostgroups, MOD_PROCESSORS, items_func, class_check) + self.replace_with_import(self.hostgroups, MOD_PROCESSORS, items_func, class_check) services = [] - for hg in hostgroups: + for hg in self.hostgroups: services.extend(hg.get_services()) items_func = lambda service: service.get_parser() @@ -241,7 +241,7 @@ class FullConfigParser(ConfigParser): #replace object pointer id_list_func = lambda hostgroup: hostgroup.get_members() id_get_func = lambda member: member.get_id() - self.replace_pointer(hostgroups, members, id_list_func, id_get_func) + self.replace_pointer(self.hostgroups, members, id_list_func, id_get_func) id_list_func = lambda service: service.get_periods() id_get_func = lambda period: period.get_name() @@ -249,9 +249,9 @@ class FullConfigParser(ConfigParser): id_list_func = lambda layout: layout.get_hostgroups() id_get_func = lambda hostgroup: hostgroup.get_name() - self.replace_pointer(layouts, hostgroups, id_list_func, id_get_func) + self.replace_pointer(layouts, self.hostgroups, id_list_func, id_get_func) - for hg in hostgroups: + for hg in self.hostgroups: for service in hg.get_services(): service.set_hostgroup(hg) core = None diff --git a/linspector b/linspector index b245f2f..baf18bf 100755 --- a/linspector +++ b/linspector @@ -62,9 +62,16 @@ def main(): jobs = [] for layout in layouts: + for i in range(len(layout.get_hostgroups())): + hg = layout.get_hostgroups()[i] + for serv in hg.get_services(): + for service in serv: + for period in service.get_periods(): + pass + if layout.is_enabled(): - for hg in layout.get_hostgroups(): - for sr in hg.get_services(): + for hostgroup in layout.get_hostgroups(): + for sr in hostgroup.get_services(): if not isinstance(sr, list): sr = sr.get_hostgroup().get_services() for s in sr: From 2389a5f61522a5cf9873869b2d6d9aa682eda1cf Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 01:36:51 +0200 Subject: [PATCH 131/268] very very strange python, One day I'll pay you back! --- lib/config/hostgroups.py | 8 +++++--- linspector | 20 ++++++++++++++------ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 8719f88..1b3971e 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -11,7 +11,7 @@ class HostGroupMissingArgumentException(HostGroupException): super(HostGroupMissingArgumentException, self).__init__("no " + missingArgument + " defined for Hostgroup " + hostgroupName) -class HostGroup: +class HostGroup(object): def __init__(self, name, **kwargs): self.name = name tmp = "members" @@ -92,7 +92,9 @@ class HostGroup: return self.members def __str__(self): - ret = "HostGroup: " + self.name + " threshold: " + str(self.threshold) + " parent: " + self.parent + "\n" + if True: + return str(self.__dict__) + ret = "HostGroup: " + self.name + "\n" ret += "members: {\n" for itm in self.members: ret += str(itm) + "\n" @@ -102,7 +104,7 @@ class HostGroup: ret += str(itm) + "\n" ret += "}\n" ret += "services: {\n" - for itm in self.services: + for itm in self._services: ret += str(itm) + "\n" ret += "}\n" return ret diff --git a/linspector b/linspector index baf18bf..f50a168 100755 --- a/linspector +++ b/linspector @@ -62,16 +62,24 @@ def main(): jobs = [] for layout in layouts: - for i in range(len(layout.get_hostgroups())): - hg = layout.get_hostgroups()[i] - for serv in hg.get_services(): - for service in serv: - for period in service.get_periods(): - pass + #for i in range(len(layout._hostgroups)): + # for y in range(len(layout._hostgroups[i])._services): + # for period in layout.get_hostgroups()[i]._services[y]: + # log.i("wtf") + # for serv in layout.get_hostgroups()[i].get_services(): + # for service in serv: + # for period in service.get_periods(): + # pass if layout.is_enabled(): for hostgroup in layout.get_hostgroups(): for sr in hostgroup.get_services(): + if not isinstance(sr, list): + + log.i("check from hostgroup: id(" + str(id(hostgroup)) + ") " + str(hostgroup)) + log.i("check from sr.get_hostgroup(): id(" + str(id(sr.get_hostgroup)) + ") " + str(sr.get_hostgroup())) + sr = hostgroup.__dict__["_services"] + if not isinstance(sr, list): sr = sr.get_hostgroup().get_services() for s in sr: From 311bdc36b1c03b097d97183188da6c2ba9f56688 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 01:43:18 +0200 Subject: [PATCH 132/268] very very strange python, One day I'll pay you back! --- lib/config/hostgroups.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 1b3971e..a3412ba 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -27,7 +27,7 @@ class HostGroup(object): self.add_hosts(kwargs[tmp]) tmp = "services" - self._services = [] + self.__services = [] if not tmp in kwargs: raise HostGroupMissingArgumentException(tmp, name) self.add_services(kwargs[tmp]) @@ -80,7 +80,7 @@ class HostGroup(object): return self.processors def get_services(self): - return self._services + return self.__services def get_hosts(self): return self.hosts From d1510a2407351a5aa25abdffe18a87b8afee9e8f Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 01:46:05 +0200 Subject: [PATCH 133/268] very very strange python, One day I'll pay you back! --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index f50a168..76e352b 100755 --- a/linspector +++ b/linspector @@ -78,7 +78,7 @@ def main(): log.i("check from hostgroup: id(" + str(id(hostgroup)) + ") " + str(hostgroup)) log.i("check from sr.get_hostgroup(): id(" + str(id(sr.get_hostgroup)) + ") " + str(sr.get_hostgroup())) - sr = hostgroup.__dict__["_services"] + sr = hostgroup.__dict__["_HostGroup__services"] if not isinstance(sr, list): sr = sr.get_hostgroup().get_services() From 73c2c2cd92e08b96119899e1aa520c71c1957c70 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 20 Jun 2013 01:53:26 +0200 Subject: [PATCH 134/268] very very strange python, One day I'll pay you back! --- lib/config/hostgroups.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index a3412ba..929a23f 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -80,7 +80,10 @@ class HostGroup(object): return self.processors def get_services(self): - return self.__services + s = self.__services + if not isinstance(s, list): + s = self.__dict__["_HostGroup__services"] + return s def get_hosts(self): return self.hosts From 1f095725b63ef17869a38fc3874abeebb55dca27 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 21 Jun 2013 01:46:08 +0200 Subject: [PATCH 135/268] too bad, long nights, all good (nearly) --- lib/config/hostgroups.py | 9 +++------ lib/config/layouts.py | 2 +- lib/config/parser.py | 1 - lib/core/job.py | 2 +- linspector | 24 +++--------------------- 5 files changed, 8 insertions(+), 30 deletions(-) diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 929a23f..047bf13 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -57,7 +57,7 @@ class HostGroup(object): l.extend(item) else: l.append(item) - + def add_members(self, member): self.__add_internal(self.get_members(), member) @@ -80,11 +80,8 @@ class HostGroup(object): return self.processors def get_services(self): - s = self.__services - if not isinstance(s, list): - s = self.__dict__["_HostGroup__services"] - return s - + return self.__services + def get_hosts(self): return self.hosts diff --git a/lib/config/layouts.py b/lib/config/layouts.py index c045869..f17d8a7 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -6,7 +6,7 @@ class LayoutException(Exception): return repr(self.msg) -class Layout: +class Layout(object): def __init__(self, name, enabled=False, hostgroups=None): self._name = name self._enabled = enabled diff --git a/lib/config/parser.py b/lib/config/parser.py index b5fd4d3..e8daf8d 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -10,7 +10,6 @@ from members import Member from periods import CronPeriod, DatePeriod, IntervalPeriod from lib.services.service import Service -#print id(Service) from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task diff --git a/lib/core/job.py b/lib/core/job.py index 8f61e52..2608f2b 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -3,7 +3,7 @@ This is what job_function needs as parameter for each job to successfully execute. """ -from command import Command +from lib.core.command import Command def generateId(): diff --git a/linspector b/linspector index 76e352b..2e031cc 100755 --- a/linspector +++ b/linspector @@ -62,29 +62,11 @@ def main(): jobs = [] for layout in layouts: - #for i in range(len(layout._hostgroups)): - # for y in range(len(layout._hostgroups[i])._services): - # for period in layout.get_hostgroups()[i]._services[y]: - # log.i("wtf") - # for serv in layout.get_hostgroups()[i].get_services(): - # for service in serv: - # for period in service.get_periods(): - # pass - if layout.is_enabled(): for hostgroup in layout.get_hostgroups(): - for sr in hostgroup.get_services(): - if not isinstance(sr, list): - - log.i("check from hostgroup: id(" + str(id(hostgroup)) + ") " + str(hostgroup)) - log.i("check from sr.get_hostgroup(): id(" + str(id(sr.get_hostgroup)) + ") " + str(sr.get_hostgroup())) - sr = hostgroup.__dict__["_HostGroup__services"] - - if not isinstance(sr, list): - sr = sr.get_hostgroup().get_services() - for s in sr: - for period in s.get_periods(): - jobs.append(period.createJob(scheduler, s, handleJob)) + for service in hostgroup.s: + for period in service.get_periods(): + jobs.append(period.createJob(scheduler, service, handleJob)) scheduler.start() #log.i("starting linspector: reading config... (" + args.config + ")") From f1fedb163a0480867543e6dd63bec45161b4de75 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 21 Jun 2013 01:47:30 +0200 Subject: [PATCH 136/268] too bad, long nights, all good (nearly) --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 2e031cc..49ea042 100755 --- a/linspector +++ b/linspector @@ -64,7 +64,7 @@ def main(): for layout in layouts: if layout.is_enabled(): for hostgroup in layout.get_hostgroups(): - for service in hostgroup.s: + for service in hostgroup.get_services(): for period in service.get_periods(): jobs.append(period.createJob(scheduler, service, handleJob)) scheduler.start() From e27f14a22a77956e98cf19fb1415832f18185038 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 21 Jun 2013 01:57:32 +0200 Subject: [PATCH 137/268] parsing is finally done! --- lib/config/periods.py | 5 ++++- linspector | 4 ++-- minimal.json | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/config/periods.py b/lib/config/periods.py index a0c2a56..22c8140 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -66,4 +66,7 @@ class DatePeriod(Period): return ret def createJob(self, scheduler, jobInfo, func): - return scheduler.add_date_job(func, self.date, jobInfo) \ No newline at end of file + try: + return scheduler.add_date_job(func=func, date=self.date, args=[jobInfo]) + except Exception, e: + return None \ No newline at end of file diff --git a/linspector b/linspector index 49ea042..2e60ac2 100755 --- a/linspector +++ b/linspector @@ -59,7 +59,7 @@ def main(): scheduler = Scheduler() - + scheduler.start() jobs = [] for layout in layouts: if layout.is_enabled(): @@ -67,7 +67,7 @@ def main(): for service in hostgroup.get_services(): for period in service.get_periods(): jobs.append(period.createJob(scheduler, service, handleJob)) - scheduler.start() + #log.i("starting linspector: reading config... (" + args.config + ")") #config_parser = ConfigParser(log) diff --git a/minimal.json b/minimal.json index 1c459bc..8aedea2 100644 --- a/minimal.json +++ b/minimal.json @@ -9,7 +9,7 @@ "periods": { "doh": {"seconds": 10, "comment": "OMG, this means work"}, "moes_time": {"minute":"0", "hour": "12", "day_of_week": "4", "comment": "much better"}, - "marges_birthday": { "date": "1965-2-24 04:00:00"} + "marges_birthday": { "date": "2017-2-24 04:00:00"} }, "hostgroups":{ "power_plant":{ From 1aa1d6ba4326c3746c867c77c41897301c939ebe Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 21 Jun 2013 02:20:58 +0200 Subject: [PATCH 138/268] Linspector is running, again!! --- lib/core/job.py | 44 +++++++++++++------------------------------- linspector | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 33 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index 2608f2b..80ea35a 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -14,42 +14,24 @@ def generateId(): class JobInfo: - def __init__(self, hostgroupname, members, hosts, hostServices, threshold, parent=None): - self.members = members - self.hosts = hosts - self.hostServices = hostServices - self.threshold = threshold - self.parent = parent + def __init__(self, service): + self.service = service self.name = generateId() - #self.name = hostgroupname + str([str("_" + s.service.name ) for s in hostServices]) - self.jobs = [] + self.job = None def __str__(self): return "JobInfo " + str(self.name) - def setLogger(self, log): + def set_logger(self, log): self.log = log - - def appendJob(self, job): - self.jobs.append(job) - - def getNextExecutionTime(self): - nextExecution = None - for job in self.jobs: - jobExec = job.trigger.get_next_fire_time() - if nextExecution is None or nextExecution > jobExec: - nextExecution = jobExec - return nextExecution - - def handleCall(self): + + def set_job(self, job): + self.job = job + + def handle_call(self): self.log.d("handle call") - self.log.d(self.hostServices) + self.log.d(self.service) try: - - for hs in self.hostServices: - self.log.d(str(hs)) - cmd = Command(hs.service.command, self.log) - cmd.call() - self.log.d(cmd.getAllOutput()) - except Exception: - self.log.d(Exception) \ No newline at end of file + self.service._execute() + except Exception, e: + self.log.d(e) \ No newline at end of file diff --git a/linspector b/linspector index 2e60ac2..0b92a19 100755 --- a/linspector +++ b/linspector @@ -11,6 +11,7 @@ from lib.core.job import JobInfo from lib.core.logger import Logger from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler +from lib.core.job import JobInfo log = None @@ -44,7 +45,7 @@ def parseArgs(): def handleJob(jobInfo): - log.w(jobInfo) + jobInfo.handle_call() def main(): @@ -66,7 +67,16 @@ def main(): for hostgroup in layout.get_hostgroups(): for service in hostgroup.get_services(): for period in service.get_periods(): - jobs.append(period.createJob(scheduler, service, handleJob)) + jobInfo = JobInfo(service) + job = period.createJob(scheduler, jobInfo, handleJob) + if job is not None: + jobInfo.set_job(job) + jobInfo.set_logger(log) + jobs.append(jobInfo) + + while True: + #Todo: implement user handle + time.sleep(10) #log.i("starting linspector: reading config... (" + args.config + ")") From ad190f30e941435f8ee05f0b88f37e9a51ae905a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 21 Jun 2013 03:02:20 +0200 Subject: [PATCH 139/268] deleted docs/. makes no sense to have it in the repo. just create your own using the Makefile From e018ade717e78f9c1e79df3d3aebad9828ac8d4b Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 21 Jun 2013 03:05:02 +0200 Subject: [PATCH 140/268] uups, forgot to add docs/ to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1c99887..4586a6c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ nbproject *.so distfiles +docs files local log From a5bd6cfed679b45ada5347fad1d5ae0031b32872 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 21 Jun 2013 03:34:10 +0200 Subject: [PATCH 141/268] it was housekeeping... call it whitespacing... whatever! --- lib/config/parser.py | 6 +++--- lib/processors/mariadb.py | 2 +- lib/processors/mongodb.py | 2 +- lib/processors/syslog.py | 2 +- linspector | 2 -- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index e8daf8d..e40a833 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -242,12 +242,12 @@ class FullConfigParser(ConfigParser): id_get_func = lambda member: member.get_id() self.replace_pointer(self.hostgroups, members, id_list_func, id_get_func) - id_list_func = lambda service: service.get_periods() + id_list_func = lambda service: service.get_periods() id_get_func = lambda period: period.get_name() self.replace_pointer(services, periods, id_list_func, id_get_func) id_list_func = lambda layout: layout.get_hostgroups() - id_get_func = lambda hostgroup: hostgroup.get_name() + id_get_func = lambda hostgroup: hostgroup.get_name() self.replace_pointer(layouts, self.hostgroups, id_list_func, id_get_func) for hg in self.hostgroups: @@ -257,4 +257,4 @@ class FullConfigParser(ConfigParser): if "core" in self.jsonDict: core = self.jsonDict["core"] - return (layouts, core) \ No newline at end of file + return layouts, core \ No newline at end of file diff --git a/lib/processors/mariadb.py b/lib/processors/mariadb.py index d077d5b..2d09875 100644 --- a/lib/processors/mariadb.py +++ b/lib/processors/mariadb.py @@ -7,7 +7,7 @@ from lib.processors.processor import Processor class MariadbProcessor(Processor): def __init__(self, **kwargs): - pass + Processor.__init__(self, **kwargs) def create(kwargs): diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 5c521f5..52ba222 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -7,7 +7,7 @@ from lib.processors.processor import Processor class MongodbProcessor(Processor): def __init__(self, **kwargs): - pass + Processor.__init__(self, **kwargs) def create(kwargs): diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index 84897fa..be5c0cf 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -7,7 +7,7 @@ from lib.processors.processor import Processor class SyslogProcessor(Processor): def __init__(self, **kwargs): - pass + Processor.__init__(self, **kwargs) def create(kwargs): diff --git a/linspector b/linspector index 0b92a19..0a6c4cc 100755 --- a/linspector +++ b/linspector @@ -13,7 +13,6 @@ from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler from lib.core.job import JobInfo -log = None def parseArgs(): parser = argparse.ArgumentParser( @@ -78,7 +77,6 @@ def main(): #Todo: implement user handle time.sleep(10) - #log.i("starting linspector: reading config... (" + args.config + ")") #config_parser = ConfigParser(log) #config = config_parser.parse_config(args.config) From 2f398d78ff1d9c934539d4f5d5624beaa95f333f Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Sun, 23 Jun 2013 02:25:38 +0200 Subject: [PATCH 142/268] added ping service --- lib/services/ping.py | 236 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 236 insertions(+) diff --git a/lib/services/ping.py b/lib/services/ping.py index 5553e09..489dc91 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -4,11 +4,247 @@ The ping service in pure Python. # http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ from lib.services.service import Service +import struct +class Packet(object): + + """Creates ICMPv4 and v6 packets. + + header + two-item sequence containing the type and code of the packet, + respectively. + version + Automatically set to version of protocol being used or None if ambiguous. + data + Contains data of the packet. Can only assign a subclass of basestring + or None. + + packet + binary representation of packet. + + """ + + header_table = { + 0 : (0, 4), + #3 : (15, 4), Overlap with ICMPv6 + 3 : (15, None), + #4 : (0, 4), Deprecated by RFC 1812 + 5 : (3, 4), + 8 : (0, 4), + 9 : (0, 4), + 10: (0, 4), + 11: (1, 4), + 12: (1, 4), + 13: (0, 4), + 14: (0, 4), + 15: (0, 4), + 16: (0, 4), + 17: (0, 4), + 18: (0, 4), + + 1: (4, 6), + 2: (0, 6), + #3 : (2, 6), Overlap with ICMPv4 + #4 : (2, 6), Type of 4 in ICMPv4 is deprecated + 4: (2, None), + 128: (0, 6), + 129: (0, 6), + 130: (0, 6), + 131: (0, 6), + 132: (0, 6), + 133: (0, 6), + 134: (0, 6), + 135: (0, 6), + 136: (0, 6), + 137: (0, 6), + } + + def _setheader(self, header): + """Set type, code, and version for the packet.""" + if len(header) != 2: + raise ValueError("header data must be in a two-item sequence") + type_, code = header + try: + max_range, version = self.header_table[type_] + except KeyError: + raise ValueError("%s is not a valid type argument" % type_) + else: + if code > max_range: + raise ValueError("%s is not a valid code value for type %s" %\ + (type_, code)) + self._type, self._code, self._version = type_, code, version + + header = property(lambda self: (self._type, self._code), _setheader, + doc="type and code of packet") + + version = property(lambda self: self._version, + doc="Protocol version packet is using or None if " + "ambiguous") + + def _setdata(self, data): + """Setter for self.data; will only accept a basestring or None type.""" + if not isinstance(data, basestring) and not isinstance(data, type(None)): + raise TypeError("value must be a subclass of basestring or None, " + "not %s" % type(data)) + self._data = data + + data = property(lambda self: self._data, _setdata, + doc="data contained within the packet") + + def __init__(self, header=(None, None), data=None): + """Set instance attributes if given.""" + #XXX: Consider using __slots__ + # self._version initialized by setting self.header + self.header = header + self.data = data + self.type = None + self.code = None + + + def __repr__(self): + return "" % \ + (self.version, self.type, self.code, len(self.data)) + + def create(self): + """Return a packet.""" + # Kept as a separate method instead of rolling into 'packet' property so + # as to allow passing method around without having to define a lambda + # method. + args = [self.header[0], self.header[1], 0] + pack_format = "!BBH" + if self.data: + pack_format += "%ss" % len(self.data) + args.append(self.data) + # ICMPv6 has the IP stack calculate the checksum + # For ambiguous cases, just go ahead and calculate it just in case + if self.version == 4 or not self.version: + args[2] = self._checksum(struct.pack(pack_format, *args)) + return struct.pack(pack_format, *args) + + packet = property(create, + doc="Complete ICMP packet") + + def _checksum(self, checksum_packet): + """Calculate checksum""" + byte_count = len(checksum_packet) + #XXX: Think there is an error here about odd number of bytes + if byte_count % 2: + odd_byte = ord(checksum_packet[-1]) + checksum_packet = checksum_packet[:-1] + else: + odd_byte = 0 + two_byte_chunks = struct.unpack("!%sH" % (len(checksum_packet)/2), + checksum_packet) + total = 0 + for two_bytes in two_byte_chunks: + total += two_bytes + else: + total += odd_byte + total = (total >> 16) + (total & 0xFFFF) + total += total >> 16 + return ~total + + def parse(cls, packet): + """Parse ICMP packet and return an instance of Packet""" + string_len = len(packet) - 4 # Ignore IP header + pack_format = "!BBH" + if string_len: + pack_format += "%ss" % string_len + unpacked_packet = struct.unpack(pack_format, packet) + packetType, code, checksum = unpacked_packet[:3] + try: + data = unpacked_packet[3] + except IndexError: + data = None + return cls((packetType, code), data) + + parse = classmethod(parse) + + +import socket +import time +import os + + +class PingResponse(object): + def __init__(self, bufferLength, address, ident, seq, rtt): + self.bufferLength = bufferLength + self.address = address + self.ident = ident + self.seq = seq + self.rtt = rtt + + def get_response_time(self): + return self.rtt + + def __str__(self): + return "%d bytes from %s: id=%s, seq=%u, rtt=%.3f ms" % \ + (self.bufferLength, self.address, self.ident, self.seq, self.rtt) + class PingService(Service): def __init__(self, **kwargs): super(PingService, self).__init__(**kwargs) + self.dataLen = 56 + self.bufferSize = 1500 + + def execute(self, host): + self.ping(host) + + def ping(self, address): + print "PING (%s): %d data bytes" % (address, self.dataLen) + + ## create socket + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp')) + s.connect((address, 22)) + + ## setuid back to normal user + + processId = os.getpid() + os.setuid(processId) + + base_packet = Packet((8, 0)) + + + seqNum = 0 + ## create ping packet + pdata = struct.pack("!HHd", processId, seqNum, time.time()) + + ## send initial packet + base_packet.data = pdata + s.send(base_packet.packet) + + ## recv packet + buf = s.recv(self.bufferSize) + current_time = time.time() + + ## parse packet; remove IP header first + r = Packet.parse(buf[20:]) + + ## parse ping data + (ident, seq, timestamp) = struct.unpack("!HHd", r.data) + + ## calculate rounttrip time + rtt = current_time - timestamp + rtt *= 1000 + return PingResponse(len(buf), address, ident, seq, rtt) + + def parse_result(self, executionResult): + fails = {} + for host, pingResult in executionResult.items(): + for failKey, failVal in self.get_fails().items(): + respTime = pingResult.get_response_time() + if int(failVal) > int(respTime): + fails[failKey] = pingResult + return fails + + def handle_result(self, parseResult): + for member in self.get_hostgroup().get_members(): + for failKey, pingResult in parseResult.items(): + for task in member.get_tasks(): + if failKey == task.get_task_type(): + task._execute() + def create(kwargs): From c3377999621acdc32d121d3eed70de086debb27f Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Sun, 23 Jun 2013 02:29:13 +0200 Subject: [PATCH 143/268] change service --- lib/services/service.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/services/service.py b/lib/services/service.py index 9ae770f..0e1a3f3 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -32,8 +32,8 @@ class Service(object): self._fails = {} if KEY_FAILS in kwargs: - self.put_fails(kwargs[KEY_FAILS]) - + self.put_fails(kwargs[KEY_FAILS]) + self._periods = [] if KEY_PERIODS in kwargs: self.add_periods(kwargs[KEY_PERIODS]) @@ -107,11 +107,14 @@ class Service(object): def _execute(self): self.pre_execute() - executionResult = self.execute() - parseResult = self.parse_result(executionResult) + result = {} + for host in self.get_hostgroup().get_hosts(): + result[host] = self.execute(host) + + parseResult = self.parse_result(result) self.handle_result(parseResult) - def execute(self): + def execute(self, host): pass def pre_execute(self): @@ -120,7 +123,7 @@ class Service(object): def parse_result(self, executionResult): result = [] for parser in self.get_parser(): - result.append(self._parser._parse(executionResult)) + result.append(parser.parse(executionResult)) def handle_result(self, parseResult): pass \ No newline at end of file From c2db1f5ba717937d9e0dd4ad81659b5413641c40 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 27 Jun 2013 07:42:37 +0200 Subject: [PATCH 144/268] added a webserver to linspector to play a bit building an interface to the joblist. needs tornado via pip installed. totally ugly code but it's just playing around. --- linspector | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/linspector b/linspector index 0a6c4cc..01cbb2e 100755 --- a/linspector +++ b/linspector @@ -13,6 +13,9 @@ from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler from lib.core.job import JobInfo +import tornado.ioloop +import tornado.web + def parseArgs(): parser = argparse.ArgumentParser( @@ -47,6 +50,21 @@ def handleJob(jobInfo): jobInfo.handle_call() +class MainHandler(tornado.web.RequestHandler): + def get(self): + self.write("Linspector: (jobs)") + + +class JoblistHandler(tornado.web.RequestHandler): + def initialize(self, jobs): + self.jobs = jobs + + def get(self): + self.write("Linspector Job List:
") + for job in self.jobs: + self.write("JOB
") + + def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) @@ -73,6 +91,14 @@ def main(): jobInfo.set_logger(log) jobs.append(jobInfo) + application = tornado.web.Application([ + (r"/", MainHandler), + (r"/jobs", JoblistHandler, dict(jobs=scheduler.get_jobs())) + ]) + + application.listen(8888) + tornado.ioloop.IOLoop.instance().start() + while True: #Todo: implement user handle time.sleep(10) From caaf1cb87c3ab3a91fab87d9b0a9e5908c0a75d3 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 27 Jun 2013 07:56:47 +0200 Subject: [PATCH 145/268] added double ping service to show up the classItem error. see dev list for that. --- minimal.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/minimal.json b/minimal.json index 8aedea2..cf5d80f 100644 --- a/minimal.json +++ b/minimal.json @@ -19,6 +19,12 @@ {"class": "mongodb", "args":{ "host": "mongodb.burnscorp.org", "user": "homer", "password": "useless", "database": "default" }} ], "services":[ + { + "class": "ping", + "fails": {"donut": 2000}, + "periods":["doh"], + "threshold": 500 + }, { "class": "ping", "fails": {"donut": 2000}, From 209be5f76c384953d276842f0e149cda073a24c6 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 27 Jun 2013 08:38:55 +0200 Subject: [PATCH 146/268] just to make a commit i removed some newlines... ;) testing the github mail service. it should send mail to linspector-commits@lists.linspector.org on every commit now. --- lib/services/ping.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/services/ping.py b/lib/services/ping.py index 489dc91..d123ae0 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -8,7 +8,6 @@ import struct class Packet(object): - """Creates ICMPv4 and v6 packets. header @@ -101,7 +100,6 @@ class Packet(object): self.type = None self.code = None - def __repr__(self): return "" % \ (self.version, self.type, self.code, len(self.data)) @@ -182,6 +180,7 @@ class PingResponse(object): return "%d bytes from %s: id=%s, seq=%u, rtt=%.3f ms" % \ (self.bufferLength, self.address, self.ident, self.seq, self.rtt) + class PingService(Service): def __init__(self, **kwargs): super(PingService, self).__init__(**kwargs) @@ -205,7 +204,6 @@ class PingService(Service): base_packet = Packet((8, 0)) - seqNum = 0 ## create ping packet pdata = struct.pack("!HHd", processId, seqNum, time.time()) @@ -246,6 +244,5 @@ class PingService(Service): task._execute() - def create(kwargs): return PingService(**kwargs) \ No newline at end of file From 12b6e51518a52f43aef74401e21f44846f4cf2e5 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 28 Jun 2013 01:01:41 +0200 Subject: [PATCH 147/268] test --- test/PingTest.py | 10 +++++++ test/__init__.py | 1 + test/lib/__init__.py | 1 + test/lib/dummy.py | 9 ++++++ test/parsertest.py | 69 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+) create mode 100644 test/PingTest.py create mode 100644 test/__init__.py create mode 100644 test/lib/__init__.py create mode 100644 test/lib/dummy.py create mode 100755 test/parsertest.py diff --git a/test/PingTest.py b/test/PingTest.py new file mode 100644 index 0000000..2e468f0 --- /dev/null +++ b/test/PingTest.py @@ -0,0 +1,10 @@ +__author__ = 'rafael' + + +from lib.services.ping import PingService +from lib.config.hostgroups import HostGroup +from lib.config.members import Member + +member = Member() +ps = PingService(fails={"warn": 100}) +hg = HostGroup("pingGroup", members=[]) diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..f399501 --- /dev/null +++ b/test/__init__.py @@ -0,0 +1 @@ +__author__ = 'rafael' diff --git a/test/lib/__init__.py b/test/lib/__init__.py new file mode 100644 index 0000000..f399501 --- /dev/null +++ b/test/lib/__init__.py @@ -0,0 +1 @@ +__author__ = 'rafael' diff --git a/test/lib/dummy.py b/test/lib/dummy.py new file mode 100644 index 0000000..75fc3aa --- /dev/null +++ b/test/lib/dummy.py @@ -0,0 +1,9 @@ +__author__ = 'rafael' + + +class Dummy(object): + def __init__(self, **kwargs): + self.args = kwargs + +def create(args): + return Dummy(**args) diff --git a/test/parsertest.py b/test/parsertest.py new file mode 100755 index 0000000..73d0b8a --- /dev/null +++ b/test/parsertest.py @@ -0,0 +1,69 @@ +import json +import imp +import os.path as path + +class DummyParent(object): + def __init__(self, name=None, argsToReplace=None): + self.name = name + self.argsToReplace = argsToReplace + + def get_args_to_replace(self): + return self.argsToReplace + + +def replace_with_import(objList, items_func): + """ + replaces configuration dicts with their objects by importing and creating it in the first step. + In the second step the original list of json config dicts gets replaced by the loaded objects + + :param objList: the list of objects which is iterated on + :param modPart: the folder from the module (i.e tasks, parsers) + :param items_func: function to get a pointer on the list of json-config-objects to replace. Takes one argument and + should return a list of + :param class_check: currently unsupported + """ + for obj in objList: + repl = [] + items = items_func(obj) + for clazzItem in items: + try: + + clazz = clazzItem["class"] + p = path.join("lib", clazz + ".py") + mod = imp.load_source(clazz, p) + item = mod.create(clazzItem) + items.append(item) + except ImportError, err: + print "could not import " + clazz + ": " + str(clazzItem) + "! reason" + print str(err) + except KeyError, k: + print "Key " + str(k) + " not in classItem " + str(clazzItem) + except Exception, e: + print "Error while replacing class ( " + clazz + " ):" + str(e) + + del items[:] + items.extend(repl) + +jsonFile = ''' +{ + "someDummy": { + "argsToReplace": + [ + {"class": "dummy", "args": {"someargs":"ok"}}, + {"class": "dummy", "args": {"someother":"blah"}} + ] + } +} +''' + +jsonDict = json.loads(jsonFile) + +dummys=[] +for key, val in jsonDict.items(): + dummys.append(DummyParent(key, **val)) + +items_func = lambda dummy: dummy.get_args_to_replace() +replace_with_import(dummys, items_func) + + + From a81c6984896035fdf21f03e8c5a08d9011314182 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 28 Jun 2013 01:03:36 +0200 Subject: [PATCH 148/268] test --- test/parsertest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parsertest.py b/test/parsertest.py index 73d0b8a..0ddc242 100755 --- a/test/parsertest.py +++ b/test/parsertest.py @@ -32,7 +32,7 @@ def replace_with_import(objList, items_func): p = path.join("lib", clazz + ".py") mod = imp.load_source(clazz, p) item = mod.create(clazzItem) - items.append(item) + repl.append(item) except ImportError, err: print "could not import " + clazz + ": " + str(clazzItem) + "! reason" print str(err) From 9fbd3ae60706f17b18f459fb991cc73efa53cdd2 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 28 Jun 2013 01:34:31 +0200 Subject: [PATCH 149/268] test --- lib/config/parser.py | 8 +++++--- minimal.json | 13 +++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index e40a833..1a99b08 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -225,6 +225,10 @@ class FullConfigParser(ConfigParser): class_check = lambda processor: isinstance(processor, Processor) self.replace_with_import(self.hostgroups, MOD_PROCESSORS, items_func, class_check) + items_func = lambda member: member.get_tasks() + class_check = lambda task: isinstance(task, Task) + self.replace_with_import(members, MOD_TASKS, items_func, class_check) + services = [] for hg in self.hostgroups: services.extend(hg.get_services()) @@ -233,9 +237,7 @@ class FullConfigParser(ConfigParser): class_check = lambda parser: isinstance(parser, Parser) self.replace_with_import(services, MOD_PARSERS, items_func, class_check) - items_func = lambda member: member.get_tasks() - class_check = lambda task: isinstance(task, Task) - self.replace_with_import(members, MOD_TASKS, items_func, class_check) + #replace object pointer id_list_func = lambda hostgroup: hostgroup.get_members() diff --git a/minimal.json b/minimal.json index cf5d80f..9df0aa6 100644 --- a/minimal.json +++ b/minimal.json @@ -3,7 +3,8 @@ "homer":{ "name": "Homer Simpson", "comment": "Security Inspector", - "tasks": [{"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}] + "tasks": [{"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, + {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}] } }, "periods": { @@ -22,14 +23,14 @@ { "class": "ping", "fails": {"donut": 2000}, - "periods":["doh"], + "periods": ["doh"], "threshold": 500 }, { - "class": "ping", - "fails": {"donut": 2000}, - "periods":["doh"], - "threshold": 500 + "class": "ping", + "fails": {"donut": 2000}, + "periods": ["doh"], + "threshold": 500 }, { "class": "tcpconnect", From 8c067b7c8c710227844aeedf37d5b3c33d562645 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Fri, 28 Jun 2013 01:41:07 +0200 Subject: [PATCH 150/268] test --- test/parsertest.py | 44 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/test/parsertest.py b/test/parsertest.py index 0ddc242..8a2b226 100755 --- a/test/parsertest.py +++ b/test/parsertest.py @@ -11,6 +11,27 @@ class DummyParent(object): return self.argsToReplace +def _create_raw_Object(jsonDict, msgName, creator): + """ + creates an Main object from the configuration, but just parses raw data and hands it to the object + + :param jsonDict: the configuration file part as dict + :param msgName: name of object for error message + :param creator: function pointer which is taking two arguments: identifier of the object and arguments. + :should return an object + :return: a list of objects returned by creator + """ + items = [] + for key, val in jsonDict.items(): + try: + item = creator(key, val) + items.append(item) + except Exception, e: + print "ignoring " + msgName + ": " + key + "! reason:" + print e + return items + + def replace_with_import(objList, items_func): """ replaces configuration dicts with their objects by importing and creating it in the first step. @@ -46,24 +67,27 @@ def replace_with_import(objList, items_func): jsonFile = ''' { - "someDummy": { - "argsToReplace": - [ - {"class": "dummy", "args": {"someargs":"ok"}}, - {"class": "dummy", "args": {"someother":"blah"}} - ] + "tests": { + "someDummy": { + "argsToReplace": + [ + {"class": "dummy", "args": {"someargs":"ok"}}, + {"class": "dummy", "args": {"someargs":"blah"}} + ] + } } } ''' jsonDict = json.loads(jsonFile) -dummys=[] -for key, val in jsonDict.items(): - dummys.append(DummyParent(key, **val)) + +creator = lambda name, values: DummyParent(name, **values) +dummys = _create_raw_Object(jsonDict["tests"], "DummyParent", creator) items_func = lambda dummy: dummy.get_args_to_replace() replace_with_import(dummys, items_func) - +for d in dummys: + print d.__dict__ From 26fb3748b5486066b1691af423ec7bcf6f5d0b8a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 28 Jun 2013 02:05:30 +0200 Subject: [PATCH 151/268] job tornado outputtt --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 01cbb2e..4ac2e78 100755 --- a/linspector +++ b/linspector @@ -62,7 +62,7 @@ class JoblistHandler(tornado.web.RequestHandler): def get(self): self.write("Linspector Job List:
") for job in self.jobs: - self.write("JOB
") + self.write("Job: " + str(job) + "
") def main(): From 8841ea7a3c2538b0b17129884398abeaf88c151b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 2 Jul 2013 00:17:29 +0200 Subject: [PATCH 152/268] fixed ugly bug regarding KeyError "class" not in class item :) thank you StackOverflow, again! --- lib/config/parser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 1a99b08..933c780 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -105,11 +105,11 @@ class ConfigParser: """ mods = self._loadedMods[modPart] if clazz in mods: - return mods["class"] + return mods[clazz] else: #mod = __import__(clazz) - path = join("lib", modPart, clazz + ".py") - mod = imp.load_source(clazz, path) + p = join("lib", modPart, clazz + ".py") + mod = imp.load_source(clazz, p) mods[clazz] = mod return mod From 93a3d626d82a69a1af9d777e697483578e504922 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 2 Jul 2013 00:19:20 +0200 Subject: [PATCH 153/268] some cleanup --- __init__.py | 1 - lib/__init__.py | 6 --- lib/config/members.py | 6 +-- lib/core/job.py | 1 + lib/tasks/task.py | 45 +++------------------ linspector | 1 - minimal.json | 6 ++- test/__init__.py | 1 - test/lib/__init__.py | 1 - test/lib/dummy.py | 9 ----- test/parsertest.py | 93 ------------------------------------------- 11 files changed, 13 insertions(+), 157 deletions(-) delete mode 100644 test/lib/__init__.py delete mode 100644 test/lib/dummy.py delete mode 100755 test/parsertest.py diff --git a/__init__.py b/__init__.py index 4230117..e69de29 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +0,0 @@ -from lib import * diff --git a/lib/__init__.py b/lib/__init__.py index 7301f66..e69de29 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -1,6 +0,0 @@ -from config import * -from core import * -from tasks import * -from parsers import * -from processors import * -from services import * \ No newline at end of file diff --git a/lib/config/members.py b/lib/config/members.py index 1491e78..f028c96 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -2,14 +2,12 @@ import re class Member: - def __init__(self, nameid, name="", phone="", comment="", parent="", tasks=None): - self.id = nameid + def __init__(self, id, name="", comment="", tasks=None): + self.id = id self.name = name - self.phone = phone self.tasks = [] self.add_task(tasks) self.comment = comment - self.parent = parent def get_id(self): return self.id diff --git a/lib/core/job.py b/lib/core/job.py index 80ea35a..202a445 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -32,6 +32,7 @@ class JobInfo: self.log.d("handle call") self.log.d(self.service) try: + self.service._execute() except Exception, e: self.log.d(e) \ No newline at end of file diff --git a/lib/tasks/task.py b/lib/tasks/task.py index a81597e..b4c7db8 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -7,48 +7,15 @@ class Task: """ Base class for all built-in Tasks. """ - + def set_task_type(self, taskType): - """ - sets the type of this task. - - Be aware! this method can only get called once! - - :param taskType: the type of this task - """ - if hasattr(self, "_taskType"): - raise Exception("taskType is only allowed to set once!") - self.taskType = taskType - + self._taskType = taskType + def get_task_type(self): """ :return: the type set by set_type_task """ return self._taskType - - def execute_task(self, msg): - """ - this is the method tasks usually override. - It gets called anytime the task should get executed - - default does nothing - - :param msg: the msg for this task - """ - pass - - def _execute(self, taskType, msg): - """ - internal method which gets called for any member in a hostgroup. - It determines if it has an appropriate type by comparing taskType with get_task_type(). - Calls execute_task() if the type matches - - :param taskType: the type of the fail which is compared with get_task_type() - :param msg: the error message - - :return: True if execute_task() is called succesfully, else False - """ - if self.get_task_type() == taskType: - self.execute_task(msg) - return True - return False \ No newline at end of file + + def some_other_irrelevant_methods(self): + pass \ No newline at end of file diff --git a/linspector b/linspector index 4ac2e78..2980569 100755 --- a/linspector +++ b/linspector @@ -90,7 +90,6 @@ def main(): jobInfo.set_job(job) jobInfo.set_logger(log) jobs.append(jobInfo) - application = tornado.web.Application([ (r"/", MainHandler), (r"/jobs", JoblistHandler, dict(jobs=scheduler.get_jobs())) diff --git a/minimal.json b/minimal.json index 9df0aa6..9099341 100644 --- a/minimal.json +++ b/minimal.json @@ -3,8 +3,10 @@ "homer":{ "name": "Homer Simpson", "comment": "Security Inspector", - "tasks": [{"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, - {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}] + "tasks": [ + {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, + {"class":"email", "type": "do", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} + ] } }, "periods": { diff --git a/test/__init__.py b/test/__init__.py index f399501..e69de29 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1 +0,0 @@ -__author__ = 'rafael' diff --git a/test/lib/__init__.py b/test/lib/__init__.py deleted file mode 100644 index f399501..0000000 --- a/test/lib/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__author__ = 'rafael' diff --git a/test/lib/dummy.py b/test/lib/dummy.py deleted file mode 100644 index 75fc3aa..0000000 --- a/test/lib/dummy.py +++ /dev/null @@ -1,9 +0,0 @@ -__author__ = 'rafael' - - -class Dummy(object): - def __init__(self, **kwargs): - self.args = kwargs - -def create(args): - return Dummy(**args) diff --git a/test/parsertest.py b/test/parsertest.py deleted file mode 100755 index 8a2b226..0000000 --- a/test/parsertest.py +++ /dev/null @@ -1,93 +0,0 @@ -import json -import imp -import os.path as path - -class DummyParent(object): - def __init__(self, name=None, argsToReplace=None): - self.name = name - self.argsToReplace = argsToReplace - - def get_args_to_replace(self): - return self.argsToReplace - - -def _create_raw_Object(jsonDict, msgName, creator): - """ - creates an Main object from the configuration, but just parses raw data and hands it to the object - - :param jsonDict: the configuration file part as dict - :param msgName: name of object for error message - :param creator: function pointer which is taking two arguments: identifier of the object and arguments. - :should return an object - :return: a list of objects returned by creator - """ - items = [] - for key, val in jsonDict.items(): - try: - item = creator(key, val) - items.append(item) - except Exception, e: - print "ignoring " + msgName + ": " + key + "! reason:" - print e - return items - - -def replace_with_import(objList, items_func): - """ - replaces configuration dicts with their objects by importing and creating it in the first step. - In the second step the original list of json config dicts gets replaced by the loaded objects - - :param objList: the list of objects which is iterated on - :param modPart: the folder from the module (i.e tasks, parsers) - :param items_func: function to get a pointer on the list of json-config-objects to replace. Takes one argument and - should return a list of - :param class_check: currently unsupported - """ - for obj in objList: - repl = [] - items = items_func(obj) - for clazzItem in items: - try: - - clazz = clazzItem["class"] - p = path.join("lib", clazz + ".py") - mod = imp.load_source(clazz, p) - item = mod.create(clazzItem) - repl.append(item) - except ImportError, err: - print "could not import " + clazz + ": " + str(clazzItem) + "! reason" - print str(err) - except KeyError, k: - print "Key " + str(k) + " not in classItem " + str(clazzItem) - except Exception, e: - print "Error while replacing class ( " + clazz + " ):" + str(e) - - del items[:] - items.extend(repl) - -jsonFile = ''' -{ - "tests": { - "someDummy": { - "argsToReplace": - [ - {"class": "dummy", "args": {"someargs":"ok"}}, - {"class": "dummy", "args": {"someargs":"blah"}} - ] - } - } -} -''' - -jsonDict = json.loads(jsonFile) - - -creator = lambda name, values: DummyParent(name, **values) -dummys = _create_raw_Object(jsonDict["tests"], "DummyParent", creator) - -items_func = lambda dummy: dummy.get_args_to_replace() -replace_with_import(dummys, items_func) - -for d in dummys: - print d.__dict__ - From 0616ea47010db370a5ed4bdd0702d6dac0fdc4aa Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 2 Jul 2013 23:30:31 +0200 Subject: [PATCH 154/268] added job handling... a bit... :) --- lib/config/parser.py | 3 ++- lib/core/job.py | 51 ++++++++++++++++++++++++++++++----------- lib/services/service.py | 35 ++++++++++++++++++++-------- linspector | 15 ++++++------ minimal.json | 9 ++++---- 5 files changed, 77 insertions(+), 36 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 933c780..31f371e 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -12,7 +12,8 @@ from periods import CronPeriod, DatePeriod, IntervalPeriod from lib.services.service import Service from lib.processors.processor import Processor from lib.parsers.parser import Parser -from lib.tasks.task import Task +from lib.tasks.task import Task +from argparse import Namespace MOD_SERVICES = "services" MOD_PROCESSORS = "processors" diff --git a/lib/core/job.py b/lib/core/job.py index 202a445..e5b1699 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -2,9 +2,7 @@ This is what job_function needs as parameter for each job to successfully execute. """ - -from lib.core.command import Command - +from datetime import datetime def generateId(): i = 0 @@ -12,16 +10,18 @@ def generateId(): yield i i += 1 - -class JobInfo: +class Job: def __init__(self, service): self.service = service - self.name = generateId() - self.job = None + self.jobInfos = [] + self.hostThreshold = {} + for host in service.get_hostgroup().get_hosts(): + self.hostThreshold[host] = service.get_threshold() + def __str__(self): - return "JobInfo " + str(self.name) - + return str(self.__dict__) + def set_logger(self, log): self.log = log @@ -31,8 +31,33 @@ class JobInfo: def handle_call(self): self.log.d("handle call") self.log.d(self.service) - try: - self.service._execute() - except Exception, e: - self.log.d(e) \ No newline at end of file + for host in self.service.get_hostgroup().get_hosts(): + try: + jobInfo = JobInfo(host, self.service) + result = self.service._execute(host) + jobInfo.set_result(result) + jobInfo.set_successfull(self.service.was_execution_successful()) + jobInfo.set_execution_end() + + except Exception, e: + self.log.d(e) + + +class JobInfo: + def __init__(self, host, service): + self.id = generateId() + self.host = host + self.service = service + self.executionBegin = datetime.now() + + def set_result(self, result): + self.result = result + + def set_execution_end(self): + self.executionEnd = datetime.now() + + def set_execution_successful(self, successful): + self.executionSuccess = successful + + diff --git a/lib/services/service.py b/lib/services/service.py index 0e1a3f3..1fbf4ba 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -105,25 +105,40 @@ class Service(object): def needs_arguments(self): return False - def _execute(self): - self.pre_execute() - result = {} - for host in self.get_hostgroup().get_hosts(): - result[host] = self.execute(host) + def set_execution_successful(self, successful): + self.executionSuccessful = successful - parseResult = self.parse_result(result) - self.handle_result(parseResult) + def was_execution_successful(self): + return self.executionSuccessful + + def _execute(self, host): + try: + + self.set_execution_successful(True) + self.pre_execute(host) + + result = self.execute(host) + parseResult = self.parse_result(result) + self.post_execute(parseResult) + return parseResult + except Exception, e: + self.set_execution_successful(False) + self._threshold -= 1 + raise e def execute(self, host): pass - def pre_execute(self): + def pre_execute(self, host): pass def parse_result(self, executionResult): + result = [] for parser in self.get_parser(): result.append(parser.parse(executionResult)) - def handle_result(self, parseResult): - pass \ No newline at end of file + return result + + def post_execute(self, parseResult): + pass diff --git a/linspector b/linspector index 2980569..9a62347 100755 --- a/linspector +++ b/linspector @@ -7,11 +7,10 @@ import argparse import time import logging import subprocess as sp -from lib.core.job import JobInfo from lib.core.logger import Logger from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler -from lib.core.job import JobInfo +from lib.core.job import Job import tornado.ioloop import tornado.web @@ -84,12 +83,12 @@ def main(): for hostgroup in layout.get_hostgroups(): for service in hostgroup.get_services(): for period in service.get_periods(): - jobInfo = JobInfo(service) - job = period.createJob(scheduler, jobInfo, handleJob) - if job is not None: - jobInfo.set_job(job) - jobInfo.set_logger(log) - jobs.append(jobInfo) + job = Job(service) + schedulerJob = period.createJob(scheduler, job, handleJob) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(log) + jobs.append(job) application = tornado.web.Application([ (r"/", MainHandler), (r"/jobs", JoblistHandler, dict(jobs=scheduler.get_jobs())) diff --git a/minimal.json b/minimal.json index 9099341..80858d5 100644 --- a/minimal.json +++ b/minimal.json @@ -5,7 +5,7 @@ "comment": "Security Inspector", "tasks": [ {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, - {"class":"email", "type": "do", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} + {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} ] } }, @@ -26,18 +26,19 @@ "class": "ping", "fails": {"donut": 2000}, "periods": ["doh"], - "threshold": 500 + "threshold": 50 }, { "class": "ping", - "fails": {"donut": 2000}, + "fails": {"donut": 1000}, "periods": ["doh"], - "threshold": 500 + "threshold": 100 }, { "class": "tcpconnect", "args": {"port": 23232}, "periods": ["moes_time", "marges_birthday"], + "fails": {"donut": 0}, "threshold": 0, "comment": "my personal reminder, hehe" } From 07645d05586699c1d1af124747895a278eced9ce Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 13 Aug 2013 22:48:51 +0200 Subject: [PATCH 155/268] only cleanup foo... just for fun... :) --- lib/core/job.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index e5b1699..7e913c2 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -4,12 +4,14 @@ execute. """ from datetime import datetime + def generateId(): i = 0 while True: yield i i += 1 + class Job: def __init__(self, service): self.service = service @@ -17,7 +19,6 @@ class Job: self.hostThreshold = {} for host in service.get_hostgroup().get_hosts(): self.hostThreshold[host] = service.get_threshold() - def __str__(self): return str(self.__dict__) @@ -58,6 +59,4 @@ class JobInfo: self.executionEnd = datetime.now() def set_execution_successful(self, successful): - self.executionSuccess = successful - - + self.executionSuccess = successful \ No newline at end of file From 15a8c5015be11242034a302960e2705460fdc2f1 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 13 Aug 2013 22:52:16 +0200 Subject: [PATCH 156/268] he surely is... ;) --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 3deca04..231f9a1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ Johannes Findeisen - Maintainer -Rafael Timmerberg - Developer +Rafael Timmerberg - Maintainer From cabf6a96a3ebd315f57b3ddb6f1156e6aad1e4a4 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 13 Aug 2013 23:10:06 +0200 Subject: [PATCH 157/268] he surely is... ;) --- lib/frontends/__init__.py | 0 lib/frontends/frontends.py | 12 ++++++++++++ lib/frontends/https.py | 6 ++++++ lib/frontends/lish.py | 12 ++++++++++++ 4 files changed, 30 insertions(+) create mode 100644 lib/frontends/__init__.py create mode 100644 lib/frontends/frontends.py create mode 100644 lib/frontends/https.py create mode 100644 lib/frontends/lish.py diff --git a/lib/frontends/__init__.py b/lib/frontends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/frontends/frontends.py b/lib/frontends/frontends.py new file mode 100644 index 0000000..e4a3491 --- /dev/null +++ b/lib/frontends/frontends.py @@ -0,0 +1,12 @@ +''' +Just the frontends.py stub... ;) + +If linspector is being started without a frontend "enabled" it just is doing stuff like: polling, alerting, logging etc. + +Frontends a absolutely no requirement for running Linspector. +''' + + +class Frontends(): + def __init__(self, **kwargs): + return \ No newline at end of file diff --git a/lib/frontends/https.py b/lib/frontends/https.py new file mode 100644 index 0000000..a347895 --- /dev/null +++ b/lib/frontends/https.py @@ -0,0 +1,6 @@ +''' +A HTTPS frontend to the current Linspector instance. + +A Webserver listening for requests to give information about the internal state of linspector. +(maybe providing a JSON API to the instance too...) +''' diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py new file mode 100644 index 0000000..21398ec --- /dev/null +++ b/lib/frontends/lish.py @@ -0,0 +1,12 @@ +''' +The Linspector Interactive Shell... + +This will become an interface to Linspector at "start" time. Think about MidnightCommander... and then run +Linspector in a screen session and not as daemon, why not? BTW.: Daemonization is at this point of development +cancelled, because it makes no sense to daemonize everything. Linspector is a user software which will run in any +screen session perfectly. +''' + +class LishFrontend(Frontends): + def __init__(self, **kwargs): + return \ No newline at end of file From 3447dbe03f8fa90435a83e350010093a823d09ad Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Wed, 14 Aug 2013 00:39:45 +0200 Subject: [PATCH 158/268] added job handling... --- lib/core/job.py | 45 +++++++++++++++++++++++++------------- lib/services/service.py | 9 +------- lib/services/tcpconnect.py | 7 +++--- linspector | 37 +++++++------------------------ 4 files changed, 43 insertions(+), 55 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index 7e913c2..a8804bf 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -11,14 +11,12 @@ def generateId(): yield i i += 1 - class Job: - def __init__(self, service): + def __init__(self, service, host): self.service = service + self.host = host self.jobInfos = [] - self.hostThreshold = {} - for host in service.get_hostgroup().get_hosts(): - self.hostThreshold[host] = service.get_threshold() + self.jobThreshold = 0 def __str__(self): return str(self.__dict__) @@ -29,21 +27,36 @@ class Job: def set_job(self, job): self.job = job + def handle_threshold(self, serviceThreshold, executionSucessful): + if executionSucessful: + pass + else: + self.jobThreshold += 1 + + if self.jobThreshold >= serviceThreshold: + self.handle_alarm(self.jobThreshold-serviceThreshold) + + def handle_alarm(self, threholdOffset): + pass + def handle_call(self): self.log.d("handle call") self.log.d(self.service) + try: + jobInfo = JobInfo(self.host, self.service) + result = self.service._execute(self.host) + jobInfo.set_result(result) + jobInfo.set_successfull(self.service.was_execution_successful()) + jobInfo.set_execution_end() - for host in self.service.get_hostgroup().get_hosts(): - try: - jobInfo = JobInfo(host, self.service) - result = self.service._execute(host) - jobInfo.set_result(result) - jobInfo.set_successfull(self.service.was_execution_successful()) - jobInfo.set_execution_end() + self.handle_threshold(self.service.get_threshold(), self.service.was_execution_successful()) - except Exception, e: - self.log.d(e) + self.jobInfos.append(jobInfo) + + + except Exception, e: + self.log.d(e) class JobInfo: def __init__(self, host, service): @@ -59,4 +72,6 @@ class JobInfo: self.executionEnd = datetime.now() def set_execution_successful(self, successful): - self.executionSuccess = successful \ No newline at end of file + self.executionSuccess = successful + + diff --git a/lib/services/service.py b/lib/services/service.py index 1fbf4ba..faf1d36 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -15,8 +15,7 @@ class Service(object): self.add_arguments(kwargs[KEY_ARGS]) elif self.needs_arguments(): raise Exception("Error: needs arguments but none provided!") - - self._host = None + self._parser = [] if KEY_PARSER in kwargs: @@ -86,12 +85,6 @@ class Service(object): def get_comment(self): return self._comment - def set_host(self, host): - self._host = host - - def get_host(self): - return self._host - def get_parser(self): return self._parser diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 358fcfa..15b3086 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -23,17 +23,18 @@ class TcpconnectService(Service): def needs_arguments(self): return True - def execute(self, log): + def execute(self, host): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: - log.w("%s\n" % msg[1]) + + #log.w("%s\n" % msg[1]) self.errorcode = 1 try: sock.connect((self.host, self.port)) except socket.error, msg: - log.w("%s\n" % msg[1]) + #log.w("%s\n" % msg[1]) self.errorcode = 2 sock.close() diff --git a/linspector b/linspector index 9a62347..9652775 100755 --- a/linspector +++ b/linspector @@ -12,8 +12,6 @@ from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler from lib.core.job import Job -import tornado.ioloop -import tornado.web def parseArgs(): @@ -49,20 +47,6 @@ def handleJob(jobInfo): jobInfo.handle_call() -class MainHandler(tornado.web.RequestHandler): - def get(self): - self.write("Linspector: (jobs)") - - -class JoblistHandler(tornado.web.RequestHandler): - def initialize(self, jobs): - self.jobs = jobs - - def get(self): - self.write("Linspector Job List:
") - for job in self.jobs: - self.write("Job: " + str(job) + "
") - def main(): args = parseArgs() @@ -82,20 +66,15 @@ def main(): if layout.is_enabled(): for hostgroup in layout.get_hostgroups(): for service in hostgroup.get_services(): - for period in service.get_periods(): - job = Job(service) - schedulerJob = period.createJob(scheduler, job, handleJob) - if schedulerJob is not None: - job.set_job(schedulerJob) - job.set_logger(log) - jobs.append(job) - application = tornado.web.Application([ - (r"/", MainHandler), - (r"/jobs", JoblistHandler, dict(jobs=scheduler.get_jobs())) - ]) + for host in hostgroup.get_hosts(): + for period in service.get_periods(): + job = Job(service, host) + schedulerJob = period.createJob(scheduler, job, handleJob) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(log) + jobs.append(job) - application.listen(8888) - tornado.ioloop.IOLoop.instance().start() while True: #Todo: implement user handle From 7c12fe04e605ca5b77cb22606b76af1784e5527c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 20:36:35 +0200 Subject: [PATCH 159/268] some cleanups and bug fixes. --- lib/core/job.py | 11 +++++------ lib/frontends/{frontends.py => frontend.py} | 6 +++--- lib/frontends/https.py | 11 +++++++++-- lib/frontends/lish.py | 9 ++++++--- lib/services/tcpconnect.py | 3 +-- minimal.json | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) rename lib/frontends/{frontends.py => frontend.py} (90%) diff --git a/lib/core/job.py b/lib/core/job.py index a8804bf..e94c8cc 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -2,6 +2,7 @@ This is what job_function needs as parameter for each job to successfully execute. """ + from datetime import datetime @@ -11,6 +12,7 @@ def generateId(): yield i i += 1 + class Job: def __init__(self, service, host): self.service = service @@ -46,18 +48,17 @@ class Job: jobInfo = JobInfo(self.host, self.service) result = self.service._execute(self.host) jobInfo.set_result(result) - jobInfo.set_successfull(self.service.was_execution_successful()) + jobInfo.set_execution_successful(self.service.was_execution_successful()) jobInfo.set_execution_end() self.handle_threshold(self.service.get_threshold(), self.service.was_execution_successful()) - self.jobInfos.append(jobInfo) - except Exception, e: self.log.d(e) + class JobInfo: def __init__(self, host, service): self.id = generateId() @@ -72,6 +73,4 @@ class JobInfo: self.executionEnd = datetime.now() def set_execution_successful(self, successful): - self.executionSuccess = successful - - + self.executionSuccess = successful \ No newline at end of file diff --git a/lib/frontends/frontends.py b/lib/frontends/frontend.py similarity index 90% rename from lib/frontends/frontends.py rename to lib/frontends/frontend.py index e4a3491..90f43cf 100644 --- a/lib/frontends/frontends.py +++ b/lib/frontends/frontend.py @@ -1,12 +1,12 @@ -''' +""" Just the frontends.py stub... ;) If linspector is being started without a frontend "enabled" it just is doing stuff like: polling, alerting, logging etc. Frontends a absolutely no requirement for running Linspector. -''' +""" -class Frontends(): +class Frontend(): def __init__(self, **kwargs): return \ No newline at end of file diff --git a/lib/frontends/https.py b/lib/frontends/https.py index a347895..70a63dd 100644 --- a/lib/frontends/https.py +++ b/lib/frontends/https.py @@ -1,6 +1,13 @@ -''' +""" A HTTPS frontend to the current Linspector instance. A Webserver listening for requests to give information about the internal state of linspector. (maybe providing a JSON API to the instance too...) -''' +""" + +from lib.frontends.frontend import Frontend + + +class HttpsFrontend(Frontend): + def __init__(self, **kwargs): + return \ No newline at end of file diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 21398ec..5c95b8a 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -1,12 +1,15 @@ -''' +""" The Linspector Interactive Shell... This will become an interface to Linspector at "start" time. Think about MidnightCommander... and then run Linspector in a screen session and not as daemon, why not? BTW.: Daemonization is at this point of development cancelled, because it makes no sense to daemonize everything. Linspector is a user software which will run in any screen session perfectly. -''' +""" -class LishFrontend(Frontends): +from lib.frontends.frontend import Frontend + + +class LishFrontend(Frontend): def __init__(self, **kwargs): return \ No newline at end of file diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 15b3086..9482e15 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -27,12 +27,11 @@ class TcpconnectService(Service): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: - #log.w("%s\n" % msg[1]) self.errorcode = 1 try: - sock.connect((self.host, self.port)) + sock.connect((host, self.port)) except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 2 diff --git a/minimal.json b/minimal.json index 80858d5..5454d0c 100644 --- a/minimal.json +++ b/minimal.json @@ -37,7 +37,7 @@ { "class": "tcpconnect", "args": {"port": 23232}, - "periods": ["moes_time", "marges_birthday"], + "periods": ["doh"], "fails": {"donut": 0}, "threshold": 0, "comment": "my personal reminder, hehe" From bc284097633e5bf4637f949d70a533334291f1e2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 20:47:06 +0200 Subject: [PATCH 160/268] just added some prints to tcpconnect to make shure it works. should be easy now to implemented it in linspector. needs threshhold handling and alerting in job handling now. --- lib/services/tcpconnect.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 9482e15..989e60e 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -29,13 +29,16 @@ class TcpconnectService(Service): except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 1 + print(self.errorcode) try: sock.connect((host, self.port)) except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 2 + print(self.errorcode) + print(self.errorcode) sock.close() return From 8f56cbeef17f3cec899d4c6a3da396632fa46eb6 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:04:00 +0200 Subject: [PATCH 161/268] moved json files to ./examples/ and added my personal json file --- examples/hanez.json | 37 +++++++++++++++++++++ linspector.json => examples/linspector.json | 0 minimal.json => examples/minimal.json | 0 linspector | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 examples/hanez.json rename linspector.json => examples/linspector.json (100%) rename minimal.json => examples/minimal.json (100%) diff --git a/examples/hanez.json b/examples/hanez.json new file mode 100644 index 0000000..afb970d --- /dev/null +++ b/examples/hanez.json @@ -0,0 +1,37 @@ +{ + "members":{ + "homer":{ + "name": "hanez", + "comment": "Security Inspector", + "tasks": [ + {"class":"email", "type": "donut", "args": {"rcpt": "you@hanez.org"}} + ] + } + }, + "periods": { + "always": {"seconds": 10, "comment": "OMG, this means work"} + }, + "hostgroups":{ + "power_plant":{ + "members": ["homer"], + "hosts": ["a.systemchaos.org"], + "processors":[ + {"class": "mongodb", "args":{ "host": "mongodb.hanez.org", "user": "homer", "password": "useless", "database": "default" }} + ], + "services":[ + { + "class": "tcpconnect", + "args": {"port": 80}, + "periods": ["always"], + "fails": {"donut": 0}, + "threshold": 0, + "comment": "my personal reminder, hehe" + } + ] + } + }, + "layouts":{ + "main":{"hostgroups": ["power_plant"], "enabled": true} + } + +} \ No newline at end of file diff --git a/linspector.json b/examples/linspector.json similarity index 100% rename from linspector.json rename to examples/linspector.json diff --git a/minimal.json b/examples/minimal.json similarity index 100% rename from minimal.json rename to examples/minimal.json diff --git a/linspector b/linspector index 9652775..c241646 100755 --- a/linspector +++ b/linspector @@ -1,7 +1,7 @@ #!/usr/bin/python2.7 -tt __version__ = "0.4/TETRIS" -__default_config__ = "./minimal.json" +__default_config__ = "./examples/minimal.json" import argparse import time From 7b9307b7f3313a340bf340dddde22e46998ee396 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:06:29 +0200 Subject: [PATCH 162/268] style fixs and version bump to 0.5... ;) --- linspector | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/linspector b/linspector index c241646..8b39a0d 100755 --- a/linspector +++ b/linspector @@ -1,6 +1,6 @@ #!/usr/bin/python2.7 -tt -__version__ = "0.4/TETRIS" +__version__ = "0.5/TEKKEN" __default_config__ = "./examples/minimal.json" import argparse @@ -13,7 +13,6 @@ from apscheduler.scheduler import Scheduler from lib.core.job import Job - def parseArgs(): parser = argparse.ArgumentParser( description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", @@ -47,7 +46,6 @@ def handleJob(jobInfo): jobInfo.handle_call() - def main(): args = parseArgs() log = Logger(args.logfile, args.loglevel) @@ -75,21 +73,10 @@ def main(): job.set_logger(log) jobs.append(job) - while True: #Todo: implement user handle time.sleep(10) - #log.i("starting linspector: reading config... (" + args.config + ")") - #config_parser = ConfigParser(log) - #config = config_parser.parse_config(args.config) - #log.d("parsed config: " + str(config)) - - #while True: - # time.sleep(10) - # for job in jobs: - # log.d(str(job)) - elif args.action == "stop": log.i("stopping linspector is currently unsupported") elif args.action == "restart": From b2e93ba2413a74b461fbe7284312c8634b202ee0 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:20:20 +0200 Subject: [PATCH 163/268] added dev/ folder and moved NOTES.* and TODO file to it. it is overhead in the root. --- NOTES.hanez => dev/NOTES.hanez | 0 NOTES.ruff => dev/NOTES.ruff | 0 TODO => dev/TODO | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename NOTES.hanez => dev/NOTES.hanez (100%) rename NOTES.ruff => dev/NOTES.ruff (100%) rename TODO => dev/TODO (100%) diff --git a/NOTES.hanez b/dev/NOTES.hanez similarity index 100% rename from NOTES.hanez rename to dev/NOTES.hanez diff --git a/NOTES.ruff b/dev/NOTES.ruff similarity index 100% rename from NOTES.ruff rename to dev/NOTES.ruff diff --git a/TODO b/dev/TODO similarity index 100% rename from TODO rename to dev/TODO From 929b650a72a6de1d0b54445cb9a657670dbe9115 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:38:22 +0200 Subject: [PATCH 164/268] Just a small fix. --- lib/services/tcpconnect.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 989e60e..037d6b4 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -29,14 +29,12 @@ class TcpconnectService(Service): except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 1 - print(self.errorcode) try: sock.connect((host, self.port)) except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 2 - print(self.errorcode) print(self.errorcode) sock.close() From 39eb589b31f8634b506e56b8170f3bd3f435ced7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:39:11 +0200 Subject: [PATCH 165/268] hanez.json is the most minimal and working json file. just change the port or host to something non existent and it will raise an error. --- examples/hanez.json | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index afb970d..d5d6649 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -1,37 +1,31 @@ { "members":{ - "homer":{ - "name": "hanez", - "comment": "Security Inspector", + "hanez":{ + "name": "Johannes Findeisen", "tasks": [ - {"class":"email", "type": "donut", "args": {"rcpt": "you@hanez.org"}} + { "class":"email", "type": "email", "args": { "rcpt": "you@hanez.org" }} ] } }, "periods": { - "always": {"seconds": 10, "comment": "OMG, this means work"} + "always": { "seconds": 5, "comment": "Yes, yes, yes!" } }, "hostgroups":{ - "power_plant":{ - "members": ["homer"], + "hanez":{ + "members": ["hanez"], "hosts": ["a.systemchaos.org"], - "processors":[ - {"class": "mongodb", "args":{ "host": "mongodb.hanez.org", "user": "homer", "password": "useless", "database": "default" }} - ], "services":[ { "class": "tcpconnect", - "args": {"port": 80}, + "args": { "port": 80 }, "periods": ["always"], - "fails": {"donut": 0}, - "threshold": 0, - "comment": "my personal reminder, hehe" + "fails": { "email": 0 }, + "threshold": 10 } ] } }, "layouts":{ - "main":{"hostgroups": ["power_plant"], "enabled": true} + "main":{ "hostgroups": ["hanez"], "enabled": true } } - } \ No newline at end of file From fcb59f322a557e0042ef04d7790ac4179dd5dd9e Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:46:06 +0200 Subject: [PATCH 166/268] deleted tests folder... no use for it anymore atm. --- test/PingTest.py | 10 ---------- test/__init__.py | 0 2 files changed, 10 deletions(-) delete mode 100644 test/PingTest.py delete mode 100644 test/__init__.py diff --git a/test/PingTest.py b/test/PingTest.py deleted file mode 100644 index 2e468f0..0000000 --- a/test/PingTest.py +++ /dev/null @@ -1,10 +0,0 @@ -__author__ = 'rafael' - - -from lib.services.ping import PingService -from lib.config.hostgroups import HostGroup -from lib.config.members import Member - -member = Member() -ps = PingService(fails={"warn": 100}) -hg = HostGroup("pingGroup", members=[]) diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29..0000000 From 6a57806e7f379ebd02800ed9f7b6e7e26317558c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 21:57:58 +0200 Subject: [PATCH 167/268] small cleanups and a beautiful new whitespace in output... ;) --- lib/config/parser.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 31f371e..f144020 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,8 +1,6 @@ from os.path import isfile from os.path import join -from os import getcwd import json -import sys import imp from layouts import Layout from hostgroups import HostGroup @@ -13,7 +11,6 @@ from lib.services.service import Service from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task -from argparse import Namespace MOD_SERVICES = "services" MOD_PROCESSORS = "processors" @@ -145,7 +142,7 @@ class ConfigParser: except KeyError, k: self.log.w("Key " + str(k) + " not in classItem " + str(clazzItem)) except Exception, e: - self.log.w("Error while replacing class ( " + clazz + " ):" + str(e)) + self.log.w("Error while replacing class ( " + clazz + " ): " + str(e)) del items[:] items.extend(repl) @@ -237,8 +234,6 @@ class FullConfigParser(ConfigParser): items_func = lambda service: service.get_parser() class_check = lambda parser: isinstance(parser, Parser) self.replace_with_import(services, MOD_PARSERS, items_func, class_check) - - #replace object pointer id_list_func = lambda hostgroup: hostgroup.get_members() From 79a8f5edcf918ef69413d1edba690d581fe7c2b1 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 22:50:47 +0200 Subject: [PATCH 168/268] deleted old config.py object... no need for that anymore. --- lib/config/config.py | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 lib/config/config.py diff --git a/lib/config/config.py b/lib/config/config.py deleted file mode 100644 index 4ce130e..0000000 --- a/lib/config/config.py +++ /dev/null @@ -1,26 +0,0 @@ -import json -from tasks import parseTaskList -from members import parseMemberList - -#from hostgroups import parseHostGroupList -#from layouts import parseLayoutList - - -class Config: - def __init__(self, configFile, log): - self.configfile = configFile - f = open(configFile) - self.config = f.read() - f.close() - - self.dict = json.loads(self.config) - - self.tasks = parseTaskList(self.dict['tasks']) - self.members = parseMemberList(self.dict['members'], self.tasks, log) - #self.periods = parsePeriodList(self.dict['periods'], log) - #self.hostgroups = parseHostGroupList(self.dict['hostgroups'], - # self.members, - # self.periods, - # log) - - #self.layouts = LayoutList(self.dict['layouts'], self.hostgroups) \ No newline at end of file From 1cde3c40f4748b35d8d0991c6e6ab80395e051c7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 23:37:49 +0200 Subject: [PATCH 169/268] just a small fix to reset the errorcode and errormessage before execution of a service --- lib/services/service.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/services/service.py b/lib/services/service.py index faf1d36..af8e076 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -123,6 +123,8 @@ class Service(object): pass def pre_execute(self, host): + self.errorcode = 0 + self.errormessage = None pass def parse_result(self, executionResult): From 88638dcede294c0acd9fd601f540ac0fcd2ffa14 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 14 Aug 2013 23:38:32 +0200 Subject: [PATCH 170/268] added one more host to hostgroup and debug stuff to python code --- examples/hanez.json | 12 +++++++----- lib/services/tcpconnect.py | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index d5d6649..509e4d4 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -8,24 +8,26 @@ } }, "periods": { - "always": { "seconds": 5, "comment": "Yes, yes, yes!" } + "always": { "seconds": 5 } }, "hostgroups":{ - "hanez":{ + "servers":{ "members": ["hanez"], - "hosts": ["a.systemchaos.org"], + "hosts": [ "a.systemchaos.org", "b.systemchaos.org" ], "services":[ { "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "fails": { "email": 0 }, "threshold": 10 } ] } }, "layouts":{ - "main":{ "hostgroups": ["hanez"], "enabled": true } + "main":{ + "hostgroups": ["servers"], + "enabled": true + } } } \ No newline at end of file diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 037d6b4..15eeecf 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -29,14 +29,17 @@ class TcpconnectService(Service): except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 1 + self.errormessage = "Could not create socket." try: sock.connect((host, self.port)) except socket.error, msg: #log.w("%s\n" % msg[1]) self.errorcode = 2 + self.errormessage = "Could not establish connection." print(self.errorcode) + print(self.errormessage) sock.close() return From cf3791a3a966bb9ee93e25600faccf1594bb6ed4 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 15 Aug 2013 00:35:16 +0200 Subject: [PATCH 171/268] inserted jobInfo object into service --- lib/core/job.py | 31 +++++++++++++++++++++++++------ lib/services/service.py | 34 +++++++++++----------------------- lib/services/tcpconnect.py | 18 +++++++++--------- 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index e94c8cc..70fc654 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -46,12 +46,10 @@ class Job: self.log.d(self.service) try: jobInfo = JobInfo(self.host, self.service) - result = self.service._execute(self.host) - jobInfo.set_result(result) - jobInfo.set_execution_successful(self.service.was_execution_successful()) + self.service._execute(jobInfo) jobInfo.set_execution_end() - self.handle_threshold(self.service.get_threshold(), self.service.was_execution_successful()) + self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) self.jobInfos.append(jobInfo) @@ -59,12 +57,18 @@ class Job: self.log.d(e) -class JobInfo: +class JobInfo(object): def __init__(self, host, service): self.id = generateId() self.host = host self.service = service self.executionBegin = datetime.now() + self._errorcode = -1 + self._message = None + self._executionSuccess = False + + def get_host(self): + return self.host def set_result(self, result): self.result = result @@ -73,4 +77,19 @@ class JobInfo: self.executionEnd = datetime.now() def set_execution_successful(self, successful): - self.executionSuccess = successful \ No newline at end of file + self._executionSuccess = successful + + def was_execution_successful(self): + return self._executionSuccess + + def set_message(self, msg): + self._message = msg + + def get_message(self): + return self._message + + def set_errorcode(self, errcode): + self._errorcode = errcode + + def get_errorcode(self): + return self._errorcode \ No newline at end of file diff --git a/lib/services/service.py b/lib/services/service.py index af8e076..da60a45 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -37,8 +37,7 @@ class Service(object): if KEY_PERIODS in kwargs: self.add_periods(kwargs[KEY_PERIODS]) - self.errorcode = 0 - self.errormessage = None + def add_arguments(self, args): for key, val in args.items(): @@ -98,42 +97,31 @@ class Service(object): def needs_arguments(self): return False - def set_execution_successful(self, successful): - self.executionSuccessful = successful - - def was_execution_successful(self): - return self.executionSuccessful - - def _execute(self, host): + def _execute(self, jobInfo): try: + self.pre_execute(jobInfo) - self.set_execution_successful(True) - self.pre_execute(host) - - result = self.execute(host) - parseResult = self.parse_result(result) - self.post_execute(parseResult) - return parseResult + self.execute(jobInfo) + self.parse_result(jobInfo) + self.post_execute(jobInfo) except Exception, e: self.set_execution_successful(False) self._threshold -= 1 raise e - def execute(self, host): + def execute(self, jobInfo): pass - def pre_execute(self, host): - self.errorcode = 0 - self.errormessage = None + def pre_execute(self, jobInfo): pass - def parse_result(self, executionResult): + def parse_result(self, jobInfo): result = [] for parser in self.get_parser(): - result.append(parser.parse(executionResult)) + result.append(parser.parse(jobInfo)) return result - def post_execute(self, parseResult): + def post_execute(self, jobInfo): pass diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 15eeecf..ea60612 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -23,25 +23,25 @@ class TcpconnectService(Service): def needs_arguments(self): return True - def execute(self, host): + def execute(self, jobInfo): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: #log.w("%s\n" % msg[1]) - self.errorcode = 1 - self.errormessage = "Could not create socket." + jobInfo.set_errorcode(1) + jobInfo.set_message("Could not create socket.") try: - sock.connect((host, self.port)) + sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: #log.w("%s\n" % msg[1]) - self.errorcode = 2 - self.errormessage = "Could not establish connection." + jobInfo.set_errorcode(2) + jobInfo.set_message("Could not establish connection.") - print(self.errorcode) - print(self.errormessage) + if jobInfo.get_errorcode() == -1: + jobInfo.set_execution_successful(True) sock.close() - return + def create(kwargs): From 70607e7149286917f1a5df102aca26baea74887e Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 00:47:40 +0200 Subject: [PATCH 172/268] just some error logging... --- lib/core/job.py | 3 +++ lib/services/tcpconnect.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lib/core/job.py b/lib/core/job.py index 70fc654..e86dafd 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -51,6 +51,9 @@ class Job: self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) + self.log.d("Error Code: " + str(jobInfo.get_errorcode())) + self.log.d("Error Message: " + str(jobInfo.get_message())) + self.jobInfos.append(jobInfo) except Exception, e: diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index ea60612..119039f 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -40,6 +40,8 @@ class TcpconnectService(Service): if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) + jobInfo.set_errorcode(0) + jobInfo.set_message("Connection successful established.") sock.close() From d34811f2c3c02928aa2d6b41d5a7d9a942ab10b7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 00:51:41 +0200 Subject: [PATCH 173/268] small fix: made logging a one liner because of multiple threads logging stuff... --- lib/core/job.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index e86dafd..f3aefa6 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -51,8 +51,7 @@ class Job: self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) - self.log.d("Error Code: " + str(jobInfo.get_errorcode())) - self.log.d("Error Message: " + str(jobInfo.get_message())) + self.log.d("Error Code: " + str(jobInfo.get_errorcode()) + " Message: " + str(jobInfo.get_message())) self.jobInfos.append(jobInfo) From e682cac953f1e7bb57c693e5106d0043c04e6b84 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 00:59:16 +0200 Subject: [PATCH 174/268] some moer error logging stuff --- lib/core/job.py | 2 +- lib/services/tcpconnect.py | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index f3aefa6..c543ce8 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -51,7 +51,7 @@ class Job: self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) - self.log.d("Error Code: " + str(jobInfo.get_errorcode()) + " Message: " + str(jobInfo.get_message())) + self.log.d("Error Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) self.jobInfos.append(jobInfo) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 119039f..a070ad9 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -27,16 +27,14 @@ class TcpconnectService(Service): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: - #log.w("%s\n" % msg[1]) jobInfo.set_errorcode(1) - jobInfo.set_message("Could not create socket.") + jobInfo.set_message("Could not create socket. (" + msg[1] + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: - #log.w("%s\n" % msg[1]) jobInfo.set_errorcode(2) - jobInfo.set_message("Could not establish connection.") + jobInfo.set_message("Could not establish connection. (" + msg[1] + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) @@ -45,6 +43,5 @@ class TcpconnectService(Service): sock.close() - def create(kwargs): return TcpconnectService(**kwargs) \ No newline at end of file From 6b19619a92c06bf7d20f499bb0b576e782cb214b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 15 Aug 2013 01:05:34 +0200 Subject: [PATCH 175/268] updated error messages --- lib/services/tcpconnect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index a070ad9..184950c 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -28,13 +28,13 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("Could not create socket. (" + msg[1] + ")") + jobInfo.set_message("Could not create socket. (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("Could not establish connection. (" + msg[1] + ")") + jobInfo.set_message("Could not establish connection to host : " + jobInfo.get_host() + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) From 0d8cc5fd6b2868101955784977efa208d89f3bc2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 01:10:52 +0200 Subject: [PATCH 176/268] some more nicer error code/message stuff in tcpconnect --- lib/services/tcpconnect.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 184950c..1010b49 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -28,18 +28,18 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("Could not create socket. (" + str(msg) + ")") + jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " to port: " + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("Could not establish connection to host : " + jobInfo.get_host() + " (" + str(msg) + ")") + jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " to port: " + str(self.port) + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) jobInfo.set_errorcode(0) - jobInfo.set_message("Connection successful established.") + jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " to port: " + str(self.port)) sock.close() From 8cd39860ae6a1d8d61b360fa7dfd0149a8c6ece9 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 15 Aug 2013 01:26:28 +0200 Subject: [PATCH 177/268] added members and processor info to job --- lib/core/job.py | 4 +++- lib/services/tcpconnect.py | 1 - linspector | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index c543ce8..39873ba 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -14,9 +14,11 @@ def generateId(): class Job: - def __init__(self, service, host): + def __init__(self, service, host, members, processors): self.service = service self.host = host + self.members = members + self.processors = processors self.jobInfos = [] self.jobThreshold = 0 diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 1010b49..971bab2 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -42,6 +42,5 @@ class TcpconnectService(Service): jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " to port: " + str(self.port)) sock.close() - def create(kwargs): return TcpconnectService(**kwargs) \ No newline at end of file diff --git a/linspector b/linspector index 8b39a0d..ad9c46f 100755 --- a/linspector +++ b/linspector @@ -66,7 +66,7 @@ def main(): for service in hostgroup.get_services(): for host in hostgroup.get_hosts(): for period in service.get_periods(): - job = Job(service, host) + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors()) schedulerJob = period.createJob(scheduler, job, handleJob) if schedulerJob is not None: job.set_job(schedulerJob) From cdd3b7f7acb05d3e9fe069ef39ddf27d5643521b Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 01:50:26 +0200 Subject: [PATCH 178/268] just some threshold fixes --- lib/core/job.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/core/job.py b/lib/core/job.py index 39873ba..bf4a474 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -33,11 +33,13 @@ class Job: def handle_threshold(self, serviceThreshold, executionSucessful): if executionSucessful: - pass + if self.jobThreshold > 0: + self.jobThreshold -= 1 else: self.jobThreshold += 1 if self.jobThreshold >= serviceThreshold: + self.log.d("ARGGHHH!!") self.handle_alarm(self.jobThreshold-serviceThreshold) def handle_alarm(self, threholdOffset): From c35b9566776be89feb016edf1b0a761b6ac52693 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 02:03:12 +0200 Subject: [PATCH 179/268] finalized the tcpconnect service. should be ready for takeoff now.... ;) --- lib/services/tcpconnect.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 971bab2..4a329c3 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -11,7 +11,6 @@ from lib.services.service import Service class TcpconnectService(Service): def __init__(self, **kwargs): - #Service.__init__(self, **kwargs) super(TcpconnectService, self).__init__(**kwargs) args = self.get_arguments() @@ -28,19 +27,24 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " to port: " + str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " to port: " + + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " to port: " + str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " to port: " + + str(self.port) + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) jobInfo.set_errorcode(0) - jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " to port: " + str(self.port)) + jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " to port: " + + str(self.port)) + sock.close() + def create(kwargs): return TcpconnectService(**kwargs) \ No newline at end of file From 8d18400b88215358cadee774f116b9a6364f1bfc Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 15 Aug 2013 02:24:05 +0200 Subject: [PATCH 180/268] the (sad) beginning of lish --- lib/frontends/lish.py | 20 ++++++++++++++++++-- linspector | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 5c95b8a..4397244 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -8,8 +8,24 @@ screen session perfectly. """ from lib.frontends.frontend import Frontend - +import argparse class LishFrontend(Frontend): def __init__(self, **kwargs): - return \ No newline at end of file + print("linspector interactive shell: Enter h or help for commands") + parser = argparse.ArgumentParser() + jobs = kwargs["jobs"] + parser.add_argument("-l", "--list", help="list current jobs") + while True: + + + rawInput = raw_input() + print(rawInput) + args = None + try: + args = parser.parse_args(rawInput) + except: + pass + + print(str(args)) + diff --git a/linspector b/linspector index ad9c46f..5ccb04c 100755 --- a/linspector +++ b/linspector @@ -8,6 +8,7 @@ import time import logging import subprocess as sp from lib.core.logger import Logger +from lib.frontends.lish import LishFrontend from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler from lib.core.job import Job @@ -75,7 +76,7 @@ def main(): while True: #Todo: implement user handle - time.sleep(10) + LishFrontend(jobs= jobs, scheduler=scheduler) elif args.action == "stop": log.i("stopping linspector is currently unsupported") From 90257756e640b434c415c8c0d33df0ec8ed68539 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 15 Aug 2013 02:34:42 +0200 Subject: [PATCH 181/268] the (better) continuation of lish :) --- lib/frontends/lish.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 4397244..747634f 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -15,6 +15,8 @@ class LishFrontend(Frontend): print("linspector interactive shell: Enter h or help for commands") parser = argparse.ArgumentParser() jobs = kwargs["jobs"] + + parser.add_argument("action", choices=["start", "stop"]) parser.add_argument("-l", "--list", help="list current jobs") while True: @@ -23,7 +25,7 @@ class LishFrontend(Frontend): print(rawInput) args = None try: - args = parser.parse_args(rawInput) + args = parser.parse_args(rawInput.split(" ")) except: pass From cb8c17188d71491d6c9159a4c128abf5772ab603 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 02:50:15 +0200 Subject: [PATCH 182/268] just an update to the json file i am using --- examples/hanez.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index 509e4d4..936c6c3 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -8,7 +8,7 @@ } }, "periods": { - "always": { "seconds": 5 } + "always": { "seconds": 2 } }, "hostgroups":{ "servers":{ @@ -19,7 +19,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 10 + "threshold": 5 } ] } From be2c5decc36bb4e8bde1fad2414568bc19ad7fd9 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 22:32:15 +0200 Subject: [PATCH 183/268] added email task code. not tested, just for future dev. --- lib/tasks/email.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 4e0bf39..f13ae36 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -2,6 +2,8 @@ The email task. """ +import smtplib +from email.mime.text import MIMEText from lib.tasks.task import Task @@ -15,7 +17,13 @@ class EmailTask(Task): self.recipient = kwargs["args"]["rcpt"] def execute_task(self, msg): - pass + message = MIMEText(msg) + message['Subject'] = 'Warning from Linspector' + message['From'] = "warning@linspector.org" + message['To'] = "foo@linspector.org" + s = smtplib.SMTP('localhost') + s.sendmail("warning@linspector.org", "foo@linspector.org", message.as_string()) + s.quit() def create(taskDict): From 0506dfd8353d8f78cc00af8b6c8aa2f1430faad5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 22:33:15 +0200 Subject: [PATCH 184/268] uups... :) --- lib/tasks/email.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tasks/email.py b/lib/tasks/email.py index f13ae36..d7e498b 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -20,9 +20,9 @@ class EmailTask(Task): message = MIMEText(msg) message['Subject'] = 'Warning from Linspector' message['From'] = "warning@linspector.org" - message['To'] = "foo@linspector.org" + message['To'] = self.recipient s = smtplib.SMTP('localhost') - s.sendmail("warning@linspector.org", "foo@linspector.org", message.as_string()) + s.sendmail("warning@linspector.org", self.recipient, message.as_string()) s.quit() From db306236d858c395b4a99f5877b1e4e1e6a96ec8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 23:41:03 +0200 Subject: [PATCH 185/268] just added a link --- lib/tasks/email.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/tasks/email.py b/lib/tasks/email.py index d7e498b..137ab85 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -1,5 +1,7 @@ """ The email task. + +http://docs.python.org/2/library/email-examples.html """ import smtplib From a1fdd330503e86d1f1698ed93cd8a6630a5922c1 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 15 Aug 2013 23:52:22 +0200 Subject: [PATCH 186/268] added xmpp frontend... may this will be fun at some time... --- lib/frontends/xmpp.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/frontends/xmpp.py diff --git a/lib/frontends/xmpp.py b/lib/frontends/xmpp.py new file mode 100644 index 0000000..6b84397 --- /dev/null +++ b/lib/frontends/xmpp.py @@ -0,0 +1,13 @@ +""" +The Linspector XMPP Frontend... + +Just for the fun in it... Linspector connects to a XMPP Server and are accepting commands from special users and can +give back information. The Linspector admin client will then be any Jabber Client... ;) +""" + +from lib.frontends.frontend import Frontend + + +class XmmpFrontend(Frontend): + def __init__(self, **kwargs): + pass \ No newline at end of file From 6946a51a2e3d65a761a475f0f04c878ea89a5af0 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Sat, 17 Aug 2013 03:38:48 +0200 Subject: [PATCH 187/268] Oh I got even more love for lish. less code, more power :) --- lib/frontends/lish.py | 171 ++++++++++++++++++++++++++++++++++++++---- linspector | 5 +- 2 files changed, 159 insertions(+), 17 deletions(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 747634f..6abead6 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -6,28 +6,171 @@ Linspector in a screen session and not as daemon, why not? BTW.: Daemonization i cancelled, because it makes no sense to daemonize everything. Linspector is a user software which will run in any screen session perfectly. """ +from requests.status_codes import title + +''' + #see http://docs.python.org/dev/library/argparse.html + + Cheat Sheet: + + ++++++++++++ Argument Parser creation +++++++++++++++++ + prog - The name of the program (default: sys.argv[0]) + usage - The string describing the program usage (default: generated from arguments added to parser) + description - Text to display before the argument help (default: none) + epilog - Text to display after the argument help (default: none) + parents - A list of ArgumentParser objects whose arguments should also be included + formatter_class - A class for customizing the help output + prefix_chars - The set of characters that prefix optional arguments (default: -) + fromfile_prefix_chars - The set of characters that prefix files from which additional arguments should be read (default: None) + argument_default - The global default value for arguments (default: None) + conflict_handler - The strategy for resolving conflicting optionals (usually unnecessary) + + + ++++++++++++++++++ add_argument() +++++++++++++++++++++ + name or flags - Either a name or a list of option strings, e.g. foo or -f, --foo. + action - The basic type of action to be taken when this argument is encountered at the command line. + nargs - The number of command-line arguments that should be consumed. + const - A constant value required by some action and nargs selections. + default - The value produced if the argument is absent from the command line. + type - The type to which the command-line argument should be converted. + choices - A container of the allowable values for the argument. + required - Whether or not the command-line option may be omitted (optionals only). + help - A brief description of what the argument does. + metavar - A name for the argument in usage messages. + dest - The name of the attribute to be added to the object returned by parse_args(). + + +++++++ add_subparsers()-> obj with one method -> add_parser() +++++++++ + + +''' from lib.frontends.frontend import Frontend -import argparse +import argparse, os +from shlex import split as shsplit +from cmd import Cmd + +VERSION = "0.1" class LishFrontend(Frontend): def __init__(self, **kwargs): - print("linspector interactive shell: Enter h or help for commands") - parser = argparse.ArgumentParser() - jobs = kwargs["jobs"] - parser.add_argument("action", choices=["start", "stop"]) - parser.add_argument("-l", "--list", help="list current jobs") - while True: + print(kwargs) + #self.jobs = kwargs["jobs"] + ns = argparse.Namespace() - rawInput = raw_input() - print(rawInput) - args = None + commander = LishCommander(kwargs) + run = True + while run: try: - args = parser.parse_args(rawInput.split(" ")) - except: - pass + commander.cmdloop("LISH - Linspector interactive shell") + except KeyboardInterrupt, ki: + run = False + except Exception, err: + print(err) + + if commander.can_exit(): + run = False + + +class Exit(Cmd, object): + def __init__(self): + super(Exit, self).__init__() + self._canExit = False + + def can_exit(self): + return self._canExit + + def do_exit(self, text): + self.exit = True + return self.can_exit() + + def help_exit(self): + print("exits linspector") + + do_EOF = do_exit + help_EOF = help_exit + + +class ShellCommander(Cmd, object): + def do_shell(self, text): + os.system(text) + + def help_shell(self): + print("execute any shell command. Can also be archieved by a '!' postfix") + + +class HostgroupCommander(Exit, object): + def __init__(self, hostgroup): + super(HostgroupCommander, self).__init__() + self.prompt = "" % hostgroup.get_name() + self._hostgroup = hostgroup + + def do_member(self, text): + print("dear maintainer, ") + print("I typed '%s', and would appreciate, if you could stay away from outside to implement it" % text) + print("must be kidding me!!!") + return True + + def help_member(self): + print("gives you control over a member of the hostgroup") + + + + +class LishCommander(Exit, ShellCommander): + + def __init__(self, kwargs): + + super(LishCommander, self).__init__() + + self.prompt = ": " + + self._layouts = kwargs["layouts"] + self._jobs = kwargs["jobs"] + self._scheduler = kwargs["scheduler"] + + self._hostgroupArgs = ["list", "select"] + + def do_hostgroup(self, text): + args = shsplit(text) + + if args[0] == "list": + print("current active Hostgroups:\n") + for l in self._layouts: + if l.is_enabled(): + print l.get_name() + space = 4 * " " + for hg in l.get_hostgroups(): + print space + hg.get_name() + print 3 * "\n" + elif args[0] == "select": + hostgroupName = args[1] + if len(hostgroupName) == 0: + print "must select an hostgroup" + for layout in self._layouts: + for lhg in layout.get_hostgroups(): + if lhg.get_name() == hostgroupName: + try: + hgCommander = HostgroupCommander(lhg) + hgCommander.cmdloop("Entering Hostmode of " + hostgroupName) + except KeyboardInterrupt, ke: + pass + + + + def help_hostgroup(self): + print ''' + help for Hostgroup + ''' + + def complete_hostgroup(self, text, line, begidx, endidx): + "hostgroup + ' '" + if begidx == 10: + return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs + + + + - print(str(args)) diff --git a/linspector b/linspector index 5ccb04c..8d58269 100755 --- a/linspector +++ b/linspector @@ -74,9 +74,8 @@ def main(): job.set_logger(log) jobs.append(job) - while True: - #Todo: implement user handle - LishFrontend(jobs= jobs, scheduler=scheduler) + frontend = LishFrontend(jobs=jobs, scheduler=scheduler, layouts=layouts) + elif args.action == "stop": log.i("stopping linspector is currently unsupported") From 6186add23be01587d49af78245ce29526c90179e Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 03:08:09 +0200 Subject: [PATCH 188/268] just small typo fixes. --- lib/frontends/frontend.py | 2 +- lib/frontends/lish.py | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/lib/frontends/frontend.py b/lib/frontends/frontend.py index 90f43cf..f953f25 100644 --- a/lib/frontends/frontend.py +++ b/lib/frontends/frontend.py @@ -3,7 +3,7 @@ Just the frontends.py stub... ;) If linspector is being started without a frontend "enabled" it just is doing stuff like: polling, alerting, logging etc. -Frontends a absolutely no requirement for running Linspector. +Frontends are absolutely no requirement for running Linspector. """ diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 6abead6..3ae6777 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -1,12 +1,14 @@ """ -The Linspector Interactive Shell... +Lish is the Linspector Interactive Shell... This will become an interface to Linspector at "start" time. Think about MidnightCommander... and then run Linspector in a screen session and not as daemon, why not? BTW.: Daemonization is at this point of development cancelled, because it makes no sense to daemonize everything. Linspector is a user software which will run in any screen session perfectly. """ -from requests.status_codes import title + +# what is this? +#from requests.status_codes import title ''' #see http://docs.python.org/dev/library/argparse.html @@ -45,12 +47,14 @@ from requests.status_codes import title ''' from lib.frontends.frontend import Frontend -import argparse, os +import argparse +import os from shlex import split as shsplit from cmd import Cmd VERSION = "0.1" + class LishFrontend(Frontend): def __init__(self, **kwargs): @@ -116,8 +120,6 @@ class HostgroupCommander(Exit, object): print("gives you control over a member of the hostgroup") - - class LishCommander(Exit, ShellCommander): def __init__(self, kwargs): @@ -157,8 +159,6 @@ class LishCommander(Exit, ShellCommander): except KeyboardInterrupt, ke: pass - - def help_hostgroup(self): print ''' help for Hostgroup @@ -167,10 +167,4 @@ class LishCommander(Exit, ShellCommander): def complete_hostgroup(self, text, line, begidx, endidx): "hostgroup + ' '" if begidx == 10: - return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs - - - - - - + return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs \ No newline at end of file From 9cf8afa3de1880e7f950a05b1674ed0adfce27f1 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 03:10:38 +0200 Subject: [PATCH 189/268] just doc stuff --- lib/frontends/lish.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 3ae6777..575ebf1 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -1,10 +1,7 @@ """ Lish is the Linspector Interactive Shell... -This will become an interface to Linspector at "start" time. Think about MidnightCommander... and then run -Linspector in a screen session and not as daemon, why not? BTW.: Daemonization is at this point of development -cancelled, because it makes no sense to daemonize everything. Linspector is a user software which will run in any -screen session perfectly. +This will become a commandline interface to Linspector. Think of a network switch or router like those from Cisco. """ # what is this? From 6ac3623fbf2e8102bd8ce63973dfec6699b1ea92 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 23:19:25 +0200 Subject: [PATCH 190/268] spelling fix --- lib/services/tcpconnect.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 4a329c3..0d8da3d 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -27,20 +27,20 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " to port: " + + jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " to port: " + + jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) jobInfo.set_errorcode(0) - jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " to port: " + + jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " on port: " + str(self.port)) sock.close() From 557fe4837a2f56f8e7adbe61164db35f2bf146c8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 23:39:13 +0200 Subject: [PATCH 191/268] no config object is logging. so why should layouts do it? --- lib/config/layouts.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/config/layouts.py b/lib/config/layouts.py index f17d8a7..a12affb 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -65,8 +65,6 @@ class LayoutList: if h is not None: l.hostgroups.append(h) else: - # TODO: replace next line with new logging - #logger.logWarningConfig(file="hostgroups", missing=group) pass self.layouts.append(l) From 5b33d500f3c6434041e3d23686cdef7a0a7d46fb Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 23:41:23 +0200 Subject: [PATCH 192/268] changed error codes. the higher the code the lower the error. --- lib/services/tcpconnect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 0d8da3d..8a498fa 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -26,14 +26,14 @@ class TcpconnectService(Service): try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: - jobInfo.set_errorcode(1) + jobInfo.set_errorcode(2) jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: - jobInfo.set_errorcode(2) + jobInfo.set_errorcode(1) jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") From 419305895742798926192c44ad05782b3235b6bd Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sun, 18 Aug 2013 23:45:12 +0200 Subject: [PATCH 193/268] many small fixes, typo and newlines... housekeeping! --- lib/core/command.py | 1 + lib/core/job.py | 6 +++--- lib/core/linspector_daemon.py | 7 +++++++ lib/services/service.py | 3 --- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/core/command.py b/lib/core/command.py index a9b8f62..e851038 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -3,6 +3,7 @@ from subprocess import Popen from subprocess import CalledProcessError from datetime import datetime as dt +#TODO: Move this to shell.py service file. this definitely is shell execution. (hanez) class Command: def __init__(self, command, log): diff --git a/lib/core/job.py b/lib/core/job.py index bf4a474..b2fcb0c 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -39,10 +39,10 @@ class Job: self.jobThreshold += 1 if self.jobThreshold >= serviceThreshold: - self.log.d("ARGGHHH!!") - self.handle_alarm(self.jobThreshold-serviceThreshold) + self.log.d("Threshold reached!") + self.handle_alarm(self.jobThreshold - serviceThreshold) - def handle_alarm(self, threholdOffset): + def handle_alarm(self, thresholdOffset): pass def handle_call(self): diff --git a/lib/core/linspector_daemon.py b/lib/core/linspector_daemon.py index b55ab19..cfdd8c4 100644 --- a/lib/core/linspector_daemon.py +++ b/lib/core/linspector_daemon.py @@ -1,6 +1,13 @@ from ..core import logger from ..core.daemon import Daemon +""" +TODO: Think about, that daemonizing this software is not our goal but when we want to that, this needs a rewrite and +should maybe move over to the daemon frontend. daemon.py will remain the the base for this and should stay in lib/core . +Since a daemon it normally not a frontend we should think about how to handle this. When daemonizing a real frontend +like "Lish" will make no sense but a frontend like "https" or "xmpp" could be useful anyway... +""" + class LinspectorDaemon(Daemon): def run(self): diff --git a/lib/services/service.py b/lib/services/service.py index da60a45..d1540e4 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -16,7 +16,6 @@ class Service(object): elif self.needs_arguments(): raise Exception("Error: needs arguments but none provided!") - self._parser = [] if KEY_PARSER in kwargs: self.add_parser(kwargs[KEY_PARSER]) @@ -36,9 +35,7 @@ class Service(object): self._periods = [] if KEY_PERIODS in kwargs: self.add_periods(kwargs[KEY_PERIODS]) - - def add_arguments(self, args): for key, val in args.items(): self._args[key] = val From 9248be5ac01d005b03e4d7e190bff4e26a5015a2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 19 Aug 2013 02:08:17 +0200 Subject: [PATCH 194/268] nice to play with ruffs Lish! that will be more fun in the future.... --- lib/frontends/lish.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 575ebf1..1a23f20 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -93,12 +93,20 @@ class Exit(Cmd, object): help_EOF = help_exit +class LogCommander(Cmd, object): + def do_log(self, text): + print("executed %s" % text) + + def help_log(self): + print("manage logging") + + class ShellCommander(Cmd, object): def do_shell(self, text): os.system(text) def help_shell(self): - print("execute any shell command. Can also be archieved by a '!' postfix") + print("execute any shell command. Can also be achieved by a '!' postfix") class HostgroupCommander(Exit, object): @@ -117,7 +125,7 @@ class HostgroupCommander(Exit, object): print("gives you control over a member of the hostgroup") -class LishCommander(Exit, ShellCommander): +class LishCommander(Exit, ShellCommander, LogCommander): def __init__(self, kwargs): From 5a2254253ce5cddf1d91cae85868dab83d42e849 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 19 Aug 2013 02:11:07 +0200 Subject: [PATCH 195/268] it really is not an error code...! it is a response code, so lets call it "Code".. ;) --- lib/core/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core/job.py b/lib/core/job.py index b2fcb0c..a50654f 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -55,7 +55,7 @@ class Job: self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) - self.log.d("Error Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) + self.log.d("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) self.jobInfos.append(jobInfo) From e8462537d3e7668c24175e6fa941ecbce5c03bac Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 20 Aug 2013 00:49:04 +0200 Subject: [PATCH 196/268] restructured a bit --- lib/config/parser.py | 16 ++++-- lib/frontends/lish.py | 120 +++++++++++++++++++----------------------- linspector | 34 +++++++----- 3 files changed, 88 insertions(+), 82 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index f144020..71c062e 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -5,6 +5,7 @@ import imp from layouts import Layout from hostgroups import HostGroup from members import Member +from config import LinspectorConfig from periods import CronPeriod, DatePeriod, IntervalPeriod from lib.services.service import Service @@ -200,14 +201,17 @@ class FullConfigParser(ConfigParser): :param configFilename: the configuration file to parse """ self.jsonDict = self._read_json_config(configFilename) + + # first step creator = lambda name, values: Layout(name,**values) layouts = self._create_raw_Object(self.jsonDict[KEY_LAYOUTS], "Layout", creator) - + creator = lambda name, values: Member(name, **values) members = self._create_raw_Object(self.jsonDict[KEY_MEMBERS], "Member", creator) - + + creator = lambda name, values: HostGroup(name, **values) self.hostgroups = self._create_raw_Object(self.jsonDict[KEY_HOSTGROUPS], "Hostgroup", creator) @@ -248,6 +252,12 @@ class FullConfigParser(ConfigParser): id_get_func = lambda hostgroup: hostgroup.get_name() self.replace_pointer(layouts, self.hostgroups, id_list_func, id_get_func) + linConf = LinspectorConfig() + linConf.set_layouts(layouts) + linConf.set_hostgroups(self.hostgroups) + linConf.set_members(members) + linConf.set_periods(periods) + for hg in self.hostgroups: for service in hg.get_services(): service.set_hostgroup(hg) @@ -255,4 +265,4 @@ class FullConfigParser(ConfigParser): if "core" in self.jsonDict: core = self.jsonDict["core"] - return layouts, core \ No newline at end of file + return linConf, core \ No newline at end of file diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 1a23f20..8c6db36 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -4,47 +4,8 @@ Lish is the Linspector Interactive Shell... This will become a commandline interface to Linspector. Think of a network switch or router like those from Cisco. """ -# what is this? -#from requests.status_codes import title - -''' - #see http://docs.python.org/dev/library/argparse.html - - Cheat Sheet: - - ++++++++++++ Argument Parser creation +++++++++++++++++ - prog - The name of the program (default: sys.argv[0]) - usage - The string describing the program usage (default: generated from arguments added to parser) - description - Text to display before the argument help (default: none) - epilog - Text to display after the argument help (default: none) - parents - A list of ArgumentParser objects whose arguments should also be included - formatter_class - A class for customizing the help output - prefix_chars - The set of characters that prefix optional arguments (default: -) - fromfile_prefix_chars - The set of characters that prefix files from which additional arguments should be read (default: None) - argument_default - The global default value for arguments (default: None) - conflict_handler - The strategy for resolving conflicting optionals (usually unnecessary) - - - ++++++++++++++++++ add_argument() +++++++++++++++++++++ - name or flags - Either a name or a list of option strings, e.g. foo or -f, --foo. - action - The basic type of action to be taken when this argument is encountered at the command line. - nargs - The number of command-line arguments that should be consumed. - const - A constant value required by some action and nargs selections. - default - The value produced if the argument is absent from the command line. - type - The type to which the command-line argument should be converted. - choices - A container of the allowable values for the argument. - required - Whether or not the command-line option may be omitted (optionals only). - help - A brief description of what the argument does. - metavar - A name for the argument in usage messages. - dest - The name of the attribute to be added to the object returned by parse_args(). - - +++++++ add_subparsers()-> obj with one method -> add_parser() +++++++++ - - -''' from lib.frontends.frontend import Frontend -import argparse import os from shlex import split as shsplit from cmd import Cmd @@ -58,8 +19,6 @@ class LishFrontend(Frontend): print(kwargs) #self.jobs = kwargs["jobs"] - ns = argparse.Namespace() - commander = LishCommander(kwargs) run = True while run: @@ -74,10 +33,25 @@ class LishFrontend(Frontend): run = False -class Exit(Cmd, object): +class CommandBase(Cmd, object): + def __init__(self): + super(CommandBase, self).__init__() + self._needs_update = False + + def get_completion(self, args, text, showOnZeroText=True): + if len(text) == 0 and showOnZeroText: + return args + else: + return [x for x in args if x.startswith(text)] + + +class Exit(CommandBase, object): def __init__(self): super(Exit, self).__init__() - self._canExit = False + self.set_can_exit(False) + + def set_can_exit(self, canExit=True): + self._canExit = canExit def can_exit(self): return self._canExit @@ -101,13 +75,24 @@ class LogCommander(Cmd, object): print("manage logging") -class ShellCommander(Cmd, object): +class ShellCommander(CommandBase, object): def do_shell(self, text): os.system(text) def help_shell(self): print("execute any shell command. Can also be achieved by a '!' postfix") + def complete_shell(self, text, line, begidx, endidx): + try: + PATH = os.environ['PATH'].split(os.pathsep) + bins = [] + for p in PATH: + bins.extend(os.listdir(p)) + + return self.get_completion(bins, text, False) + except: + pass + class HostgroupCommander(Exit, object): def __init__(self, hostgroup): @@ -133,7 +118,7 @@ class LishCommander(Exit, ShellCommander, LogCommander): self.prompt = ": " - self._layouts = kwargs["layouts"] + self._linConf = kwargs["linspectorConfig"] self._jobs = kwargs["jobs"] self._scheduler = kwargs["scheduler"] @@ -144,32 +129,37 @@ class LishCommander(Exit, ShellCommander, LogCommander): if args[0] == "list": print("current active Hostgroups:\n") - for l in self._layouts: - if l.is_enabled(): - print l.get_name() - space = 4 * " " - for hg in l.get_hostgroups(): - print space + hg.get_name() + for l in self._linConf.get_enabled_layouts(): + print l.get_name() + space = 4 * " " + for hg in l.get_hostgroups(): + print space + hg.get_name() print 3 * "\n" elif args[0] == "select": - hostgroupName = args[1] - if len(hostgroupName) == 0: - print "must select an hostgroup" - for layout in self._layouts: - for lhg in layout.get_hostgroups(): - if lhg.get_name() == hostgroupName: - try: - hgCommander = HostgroupCommander(lhg) - hgCommander.cmdloop("Entering Hostmode of " + hostgroupName) - except KeyboardInterrupt, ke: - pass + if len(args) < 2 or len(args[1]) == 0: + print("must select an hostgroup") + else: + hgName = args[1] + hg = self._linConf.get_hostgroup_by_name(hgName) + if hg is None: + print("unknown hostgroup %s! type hostgroup list to get a list of hostgroups" % hgName) + else: + try: + hgCommander = HostgroupCommander(hg) + hgCommander.cmdloop("Entering Hostmode of " + hgName + ":\n") + except KeyboardInterrupt, ke: + pass + def help_hostgroup(self): print ''' - help for Hostgroup + usage: + hostgroup list + prints a list of all hostgroups + hostgroup select HOSTGROUPNAME + select a hostgroup to make changes on it ''' def complete_hostgroup(self, text, line, begidx, endidx): - "hostgroup + ' '" if begidx == 10: - return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs \ No newline at end of file + return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs diff --git a/linspector b/linspector index 8d58269..46c7436 100755 --- a/linspector +++ b/linspector @@ -55,26 +55,32 @@ def main(): if args.action == "start": configParser = FullConfigParser(log) - layouts, core = configParser.parse_config(args.config) + linConf, core = configParser.parse_config(args.config) scheduler = Scheduler() scheduler.start() jobs = [] - for layout in layouts: - if layout.is_enabled(): - for hostgroup in layout.get_hostgroups(): - for service in hostgroup.get_services(): - for host in hostgroup.get_hosts(): - for period in service.get_periods(): - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors()) - schedulerJob = period.createJob(scheduler, job, handleJob) - if schedulerJob is not None: - job.set_job(schedulerJob) - job.set_logger(log) - jobs.append(job) - frontend = LishFrontend(jobs=jobs, scheduler=scheduler, layouts=layouts) + + + for layout in linConf.get_enabled_layouts(): + for hostgroup in layout.get_hostgroups(): + for service in hostgroup.get_services(): + for host in hostgroup.get_hosts(): + for period in service.get_periods(): + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors()) + schedulerJob = period.createJob(scheduler, job, handleJob) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(log) + jobs.append(job) + + frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) + + log.d("shutting down scheduler") + scheduler.shutdown(wait=False) + elif args.action == "stop": From 551935b32d66ff1bc1df5706791f07b37944d851 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 20 Aug 2013 00:51:02 +0200 Subject: [PATCH 197/268] restructured a bit --- lib/frontends/lish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 8c6db36..bd1b6e9 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -57,7 +57,7 @@ class Exit(CommandBase, object): return self._canExit def do_exit(self, text): - self.exit = True + self.set_can_exit() return self.can_exit() def help_exit(self): From 78361c72ffbda61b33ea3f9d4e375f93b4e4de3b Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 20 Aug 2013 00:51:57 +0200 Subject: [PATCH 198/268] added config --- lib/config/config.py | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/config/config.py diff --git a/lib/config/config.py b/lib/config/config.py new file mode 100644 index 0000000..8dd6c40 --- /dev/null +++ b/lib/config/config.py @@ -0,0 +1,58 @@ +__author__ = 'rafael' + +class LinspectorConfig(object): + def __init__(self): + self._layouts = None + self._hostgroups = None + self._members = None + self._periods = None + + def set_hostgroups(self, hostgroups): + self._hostgroups = hostgroups + + def get_hostgroups(self): + return self._hostgroups + + def set_layouts(self, layouts): + self._layouts = layouts + + def get_layouts(self): + return self._layouts + + def set_members(self, members): + self._members = members + + def get_members(self): + return self._members + + def set_periods(self, periods): + self._periods = periods + + def get_periods(self): + return self._periods + + def get_enabled_layouts(self): + return [l for l in self.get_layouts() if l.is_enabled()] + + def _get_by_name(self, items, name): + for itm in items: + if itm.get_name() == name: + return itm + return None + + def get_hostgroup_by_name(self, name): + return self._get_by_name(self.get_hostgroups(), name) + + def get_layout_by_name(self, name): + return self._get_by_name(self.get_layouts(), name) + + def get_member_by_name(self, name): + return self._get_by_name(self.get_members(), name) + + def get_period_by_name(self, name): + return self._get_by_name(self.get_periods(), name) + + + + + From 5f382da83b1cd67c2a3395ebbc4d8e0952d5efbb Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 20 Aug 2013 01:47:24 +0200 Subject: [PATCH 199/268] added config --- lib/tasks/email.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/tasks/email.py b/lib/tasks/email.py index 137ab85..4dabfee 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/email.py @@ -4,21 +4,25 @@ The email task. http://docs.python.org/2/library/email-examples.html """ -import smtplib -from email.mime.text import MIMEText +#import smtplib +#from email.mime.text import MIMEText from lib.tasks.task import Task class EmailTask(Task): def __init__(self, **kwargs): + pass + ''' if not "type" in kwargs: raise Exception("'type' not in typeDict " + str(kwargs)) if not "args" in kwargs: raise Exception("typeDict " + str(kwargs) + " has nor arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] + ''' def execute_task(self, msg): + ''' message = MIMEText(msg) message['Subject'] = 'Warning from Linspector' message['From'] = "warning@linspector.org" @@ -26,7 +30,8 @@ class EmailTask(Task): s = smtplib.SMTP('localhost') s.sendmail("warning@linspector.org", self.recipient, message.as_string()) s.quit() - + ''' + pass def create(taskDict): return EmailTask(**taskDict) \ No newline at end of file From 863ea67d06cfde085aa39aaabc90fb78b87d30a6 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Tue, 20 Aug 2013 03:06:08 +0200 Subject: [PATCH 200/268] added python --- lib/frontends/lish.py | 12 +++++++++++- linspector | 4 ---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index bd1b6e9..9fcf918 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -16,7 +16,7 @@ VERSION = "0.1" class LishFrontend(Frontend): def __init__(self, **kwargs): - print(kwargs) + #print(kwargs) #self.jobs = kwargs["jobs"] commander = LishCommander(kwargs) @@ -150,6 +150,16 @@ class LishCommander(Exit, ShellCommander, LogCommander): except KeyboardInterrupt, ke: pass + def do_python(self, text): + exec text + + def help_python(self): + print ''' + executes python using 'exec'. + ''' + + + def help_hostgroup(self): print ''' diff --git a/linspector b/linspector index 46c7436..22100c5 100755 --- a/linspector +++ b/linspector @@ -62,8 +62,6 @@ def main(): scheduler.start() jobs = [] - - for layout in linConf.get_enabled_layouts(): for hostgroup in layout.get_hostgroups(): for service in hostgroup.get_services(): @@ -81,8 +79,6 @@ def main(): log.d("shutting down scheduler") scheduler.shutdown(wait=False) - - elif args.action == "stop": log.i("stopping linspector is currently unsupported") elif args.action == "restart": From bae0e3abce2786200f711fa76a435c18cd108f39 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 19:32:10 +0200 Subject: [PATCH 201/268] added simple task handling to handle_call() method; renamed email task to mail because of some name collision in smtplib --- lib/tasks/{email.py => mail.py} | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) rename lib/tasks/{email.py => mail.py} (89%) diff --git a/lib/tasks/email.py b/lib/tasks/mail.py similarity index 89% rename from lib/tasks/email.py rename to lib/tasks/mail.py index 4dabfee..eaa28e2 100644 --- a/lib/tasks/email.py +++ b/lib/tasks/mail.py @@ -11,17 +11,14 @@ from lib.tasks.task import Task class EmailTask(Task): def __init__(self, **kwargs): - pass - ''' if not "type" in kwargs: raise Exception("'type' not in typeDict " + str(kwargs)) if not "args" in kwargs: raise Exception("typeDict " + str(kwargs) + " has nor arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - ''' - def execute_task(self, msg): + def execute(self, msg): ''' message = MIMEText(msg) message['Subject'] = 'Warning from Linspector' @@ -31,7 +28,12 @@ class EmailTask(Task): s.sendmail("warning@linspector.org", self.recipient, message.as_string()) s.quit() ''' + + print("Task executed") + print(msg) + print(self.recipient) pass + def create(taskDict): return EmailTask(**taskDict) \ No newline at end of file From 8be97eb781305c838a75c82ceac22d32c2449ca9 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 19:34:21 +0200 Subject: [PATCH 202/268] renamed email task to mail because of some name collision in smtplib --- examples/hanez.json | 5 +++-- examples/linspector.json | 6 +++--- examples/minimal.json | 4 ++-- lib/core/job.py | 4 ++++ lib/tasks/mail.py | 15 ++++----------- lib/tasks/task.py | 3 +++ 6 files changed, 19 insertions(+), 18 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index 936c6c3..04ea252 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -3,7 +3,8 @@ "hanez":{ "name": "Johannes Findeisen", "tasks": [ - { "class":"email", "type": "email", "args": { "rcpt": "you@hanez.org" }} + { "class":"mail", "type": "mail", "args": { "rcpt": "you@hanez.org" }}, + { "class":"mail", "type": "mail", "args": { "rcpt": "johannes.findeisen@com.puting.de" }} ] } }, @@ -19,7 +20,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 5 + "threshold": 1 } ] } diff --git a/examples/linspector.json b/examples/linspector.json index aae9209..a195480 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -3,7 +3,7 @@ "root":{ "name": "Admin", "comment": "The Linspector Admin", - "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, + "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, { "class": "xmpp", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] }, @@ -11,13 +11,13 @@ "name": "Johannes Findeisen", "comment": "Just a nerd doing admin stuff.", "parent": "darth", - "tasks":[{ "class": "email", "type": "warning", "args":{ "rcpt": "you@hanez.org" }}, + "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "you@hanez.org" }}, { "class": "sms", "type": "critical", "args":{ "rcpt": "+49110" }}] }, "darth":{ "name": "Darth Vader", "comment": "The father", - "tasks":{ "class": "email", "type": "warning", "args":{ "rcpt": "darth.vader@hanez.org" }} + "tasks":{ "class": "mail", "type": "warning", "args":{ "rcpt": "darth.vader@hanez.org" }} } }, "periods":{ diff --git a/examples/minimal.json b/examples/minimal.json index 5454d0c..0453708 100644 --- a/examples/minimal.json +++ b/examples/minimal.json @@ -4,8 +4,8 @@ "name": "Homer Simpson", "comment": "Security Inspector", "tasks": [ - {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, - {"class":"email", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} + {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, + {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} ] } }, diff --git a/lib/core/job.py b/lib/core/job.py index a50654f..ec1286f 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -43,6 +43,10 @@ class Job: self.handle_alarm(self.jobThreshold - serviceThreshold) def handle_alarm(self, thresholdOffset): + for member in self.service.get_hostgroup().get_members(): + for task in member.get_tasks(): + print(task) + task.execute("Task executed!") pass def handle_call(self): diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index eaa28e2..086ba01 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -4,12 +4,12 @@ The email task. http://docs.python.org/2/library/email-examples.html """ -#import smtplib -#from email.mime.text import MIMEText +import smtplib +from email.mime.text import MIMEText from lib.tasks.task import Task -class EmailTask(Task): +class MailTask(Task): def __init__(self, **kwargs): if not "type" in kwargs: raise Exception("'type' not in typeDict " + str(kwargs)) @@ -19,7 +19,6 @@ class EmailTask(Task): self.recipient = kwargs["args"]["rcpt"] def execute(self, msg): - ''' message = MIMEText(msg) message['Subject'] = 'Warning from Linspector' message['From'] = "warning@linspector.org" @@ -27,13 +26,7 @@ class EmailTask(Task): s = smtplib.SMTP('localhost') s.sendmail("warning@linspector.org", self.recipient, message.as_string()) s.quit() - ''' - - print("Task executed") - print(msg) - print(self.recipient) - pass def create(taskDict): - return EmailTask(**taskDict) \ No newline at end of file + return MailTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/task.py b/lib/tasks/task.py index b4c7db8..e8b113f 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -18,4 +18,7 @@ class Task: return self._taskType def some_other_irrelevant_methods(self): + pass + + def execute(self, msg): pass \ No newline at end of file From 12040d048427e7fe982baaec84ac52874bcb8185 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 20:50:17 +0200 Subject: [PATCH 203/268] renamed xmpp task to jabber to avoid conflicts; added simple xmpp/jabber support to tasks --- examples/hanez.json | 11 ++++++++--- examples/linspector.json | 2 +- lib/core/job.py | 2 +- lib/tasks/jabber.py | 31 +++++++++++++++++++++++++++++++ lib/tasks/xmpp.py | 22 ---------------------- 5 files changed, 41 insertions(+), 27 deletions(-) create mode 100644 lib/tasks/jabber.py delete mode 100644 lib/tasks/xmpp.py diff --git a/examples/hanez.json b/examples/hanez.json index 04ea252..b87f047 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -3,8 +3,7 @@ "hanez":{ "name": "Johannes Findeisen", "tasks": [ - { "class":"mail", "type": "mail", "args": { "rcpt": "you@hanez.org" }}, - { "class":"mail", "type": "mail", "args": { "rcpt": "johannes.findeisen@com.puting.de" }} + { "class":"jabber", "type": "jabber", "args": { "rcpt": "hanez@systemchaos.org" }} ] } }, @@ -20,7 +19,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 1 + "threshold": 10 } ] } @@ -30,5 +29,11 @@ "hostgroups": ["servers"], "enabled": true } + }, + "core":{ + "max_logfile_size": 1024000, + "max_logfile_count": 4, + "max_worker_threads": 8, + "members":[ "root" ] } } \ No newline at end of file diff --git a/examples/linspector.json b/examples/linspector.json index a195480..b12465f 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -5,7 +5,7 @@ "comment": "The Linspector Admin", "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, - { "class": "xmpp", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] + { "class": "jabber", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] }, "hanez":{ "name": "Johannes Findeisen", diff --git a/lib/core/job.py b/lib/core/job.py index ec1286f..8237e1a 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -46,7 +46,7 @@ class Job: for member in self.service.get_hostgroup().get_members(): for task in member.get_tasks(): print(task) - task.execute("Task executed!") + task.execute("Task executed for host: " + self.host) pass def handle_call(self): diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py new file mode 100644 index 0000000..8c84720 --- /dev/null +++ b/lib/tasks/jabber.py @@ -0,0 +1,31 @@ +""" +The Jabber task. + +Uses: http://xmpppy.sourceforge.net/ +""" + +import xmpp +from lib.tasks.task import Task + + +class JabberTask(Task): + def __init__(self, **kwargs): + if not "type" in kwargs: + raise Exception("'type' not in typeDict " + str(kwargs)) + if not "args" in kwargs: + raise Exception("typeDict " + str(kwargs) + " has nor arguments!") + self.set_task_type(kwargs["type"]) + self.recipient = kwargs["args"]["rcpt"] + + def execute(self, msg): + client = xmpp.Client('systemchaos.org') + client.connect(server=('systemchaos.org', 5222)) + client.auth('linspector', 'PASSWORD', 'alert') + client.sendInitPresence() + message = xmpp.Message('hanez@systemchaos.org', msg) + message.setAttr('type', 'chat') + client.send(message) + + +def create(taskDict): + return JabberTask(**taskDict) \ No newline at end of file diff --git a/lib/tasks/xmpp.py b/lib/tasks/xmpp.py deleted file mode 100644 index 91073ad..0000000 --- a/lib/tasks/xmpp.py +++ /dev/null @@ -1,22 +0,0 @@ -""" -The xmpp task. -""" - -from lib.tasks.task import Task - - -class XmppTask(Task): - def __init__(self, **kwargs): - if not "type" in kwargs: - raise Exception("'type' not in typeDict " + str(kwargs)) - if not "args" in kwargs: - raise Exception("typeDict " + str(kwargs) + " has nor arguments!") - self.set_task_type(kwargs["type"]) - self.recipient = kwargs["args"]["rcpt"] - - def execute_task(self, msg): - pass - - -def create(taskDict): - return XmppTask(**taskDict) \ No newline at end of file From 8103e33299c0be7485ebe9086b22c33196d6e74c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 21:12:03 +0200 Subject: [PATCH 204/268] just some cleanups and ideas in hanez.json --- examples/hanez.json | 12 ++++++++++-- lib/tasks/jabber.py | 2 +- lib/tasks/sms.py | 2 +- lib/tasks/task.py | 10 ---------- 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index b87f047..7efb11f 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -19,7 +19,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 10 + "threshold": 2 } ] } @@ -34,6 +34,14 @@ "max_logfile_size": 1024000, "max_logfile_count": 4, "max_worker_threads": 8, - "members":[ "root" ] + "members":[ "root" ], + "tasks": { + "jabber":{ + "server": "systemchaos.org", + "port": 5222, + "user": "linspector", + "password": "hallo_welt" + } + } } } \ No newline at end of file diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py index 8c84720..2699d4a 100644 --- a/lib/tasks/jabber.py +++ b/lib/tasks/jabber.py @@ -22,7 +22,7 @@ class JabberTask(Task): client.connect(server=('systemchaos.org', 5222)) client.auth('linspector', 'PASSWORD', 'alert') client.sendInitPresence() - message = xmpp.Message('hanez@systemchaos.org', msg) + message = xmpp.Message(self.recipient, msg) message.setAttr('type', 'chat') client.send(message) diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 3a45dfd..203ab4d 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -14,7 +14,7 @@ class SmsTask(Task): self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - def execute_task(self, msg): + def execute(self, msg): pass diff --git a/lib/tasks/task.py b/lib/tasks/task.py index e8b113f..cf88f03 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -4,21 +4,11 @@ The task class. class Task: - """ - Base class for all built-in Tasks. - """ - def set_task_type(self, taskType): self._taskType = taskType def get_task_type(self): - """ - :return: the type set by set_type_task - """ return self._taskType - def some_other_irrelevant_methods(self): - pass - def execute(self, msg): pass \ No newline at end of file From 305ec951101d54109ca2f4268c35351d130a647e Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 21:28:56 +0200 Subject: [PATCH 205/268] just cleanups --- examples/hanez.json | 4 ++-- lib/config/config.py | 12 +++++------- lib/core/job.py | 2 -- lib/tasks/jabber.py | 2 +- lib/tasks/mail.py | 2 +- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index 7efb11f..80b5db1 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -8,7 +8,7 @@ } }, "periods": { - "always": { "seconds": 2 } + "always": { "seconds": 60 } }, "hostgroups":{ "servers":{ @@ -19,7 +19,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 2 + "threshold": 5 } ] } diff --git a/lib/config/config.py b/lib/config/config.py index 8dd6c40..0ea9beb 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -1,4 +1,7 @@ -__author__ = 'rafael' +""" +The LinspectorConfig class. +""" + class LinspectorConfig(object): def __init__(self): @@ -50,9 +53,4 @@ class LinspectorConfig(object): return self._get_by_name(self.get_members(), name) def get_period_by_name(self, name): - return self._get_by_name(self.get_periods(), name) - - - - - + return self._get_by_name(self.get_periods(), name) \ No newline at end of file diff --git a/lib/core/job.py b/lib/core/job.py index 8237e1a..2d08c4c 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -45,9 +45,7 @@ class Job: def handle_alarm(self, thresholdOffset): for member in self.service.get_hostgroup().get_members(): for task in member.get_tasks(): - print(task) task.execute("Task executed for host: " + self.host) - pass def handle_call(self): self.log.d("handle call") diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py index 2699d4a..fbee02d 100644 --- a/lib/tasks/jabber.py +++ b/lib/tasks/jabber.py @@ -1,5 +1,5 @@ """ -The Jabber task. +The Jabber (XMPP) task. Uses: http://xmpppy.sourceforge.net/ """ diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index 086ba01..c03114d 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -1,5 +1,5 @@ """ -The email task. +The mail task. http://docs.python.org/2/library/email-examples.html """ From 7906f2c2fe2f29a690bde279771e0d8e83946679 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 19 Sep 2013 22:20:42 +0200 Subject: [PATCH 206/268] added Date to mail header. --- lib/tasks/mail.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index c03114d..177fe86 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -4,6 +4,7 @@ The mail task. http://docs.python.org/2/library/email-examples.html """ +import datetime import smtplib from email.mime.text import MIMEText from lib.tasks.task import Task @@ -21,6 +22,8 @@ class MailTask(Task): def execute(self, msg): message = MIMEText(msg) message['Subject'] = 'Warning from Linspector' + now = datetime.datetime.now() + message['Date'] = now.strftime("%a, %d %b %Y %H:%M:%S") message['From'] = "warning@linspector.org" message['To'] = self.recipient s = smtplib.SMTP('localhost') From c80b7d17f331c78e5d023a30f616d8ab594c7897 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 00:53:58 +0200 Subject: [PATCH 207/268] added examples/private.json to .gitignore for local usage only (containing passwords) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4586a6c..651d0e2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ local log plugins .metadata + +examples/private.json \ No newline at end of file From 172c21d82c8cbfc2fc2c1fd14443d27dbc5fa72f Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 00:55:12 +0200 Subject: [PATCH 208/268] added new task config vars to core section --- examples/hanez.json | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index 80b5db1..c009a3f 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -8,7 +8,7 @@ } }, "periods": { - "always": { "seconds": 60 } + "always": { "seconds": 2 } }, "hostgroups":{ "servers":{ @@ -19,7 +19,7 @@ "class": "tcpconnect", "args": { "port": 80 }, "periods": ["always"], - "threshold": 5 + "threshold": 2 } ] } @@ -37,10 +37,14 @@ "members":[ "root" ], "tasks": { "jabber":{ - "server": "systemchaos.org", + "host": "systemchaos.org", "port": 5222, - "user": "linspector", - "password": "hallo_welt" + "username": "USERNAME", + "password": "PASSWORD" + }, + "mail":{ + "host": "localhost", + "port": 25 } } } From 25f83c3ae9c2130b2b39a29aa112d35c952db251 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 01:21:53 +0200 Subject: [PATCH 209/268] look at hanez.json before using tasks... ;) --- examples/hanez.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index c009a3f..35ac11c 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -3,7 +3,7 @@ "hanez":{ "name": "Johannes Findeisen", "tasks": [ - { "class":"jabber", "type": "jabber", "args": { "rcpt": "hanez@systemchaos.org" }} + { "class":"jabber", "type": "jabber", "args": { "rcpt": "jabber@example.org" }} ] } }, @@ -44,7 +44,8 @@ }, "mail":{ "host": "localhost", - "port": 25 + "port": 25, + "from": "linspector@systemchaos.org" } } } From 0bfa4b3daabca6f1095d7717e5eb5277b17f1adf Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 01:23:50 +0200 Subject: [PATCH 210/268] added core config to jobs and tasks and made use of core variables raw in the tasks --- lib/core/job.py | 13 +++++++------ lib/services/tcpconnect.py | 12 ++++++------ lib/tasks/jabber.py | 9 +++++---- lib/tasks/mail.py | 8 ++++---- linspector | 2 +- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/core/job.py b/lib/core/job.py index 2d08c4c..6f8be0c 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -14,11 +14,12 @@ def generateId(): class Job: - def __init__(self, service, host, members, processors): + def __init__(self, service, host, members, processors, core): self.service = service self.host = host self.members = members self.processors = processors + self.core = core self.jobInfos = [] self.jobThreshold = 0 @@ -31,7 +32,7 @@ class Job: def set_job(self, job): self.job = job - def handle_threshold(self, serviceThreshold, executionSucessful): + def handle_threshold(self, jobInfo, serviceThreshold, executionSucessful): if executionSucessful: if self.jobThreshold > 0: self.jobThreshold -= 1 @@ -40,12 +41,12 @@ class Job: if self.jobThreshold >= serviceThreshold: self.log.d("Threshold reached!") - self.handle_alarm(self.jobThreshold - serviceThreshold) + self.handle_alarm(jobInfo, self.jobThreshold - serviceThreshold) - def handle_alarm(self, thresholdOffset): + def handle_alarm(self, jobInfo, thresholdOffset): for member in self.service.get_hostgroup().get_members(): for task in member.get_tasks(): - task.execute("Task executed for host: " + self.host) + task.execute(jobInfo.get_message(), self.core) def handle_call(self): self.log.d("handle call") @@ -55,7 +56,7 @@ class Job: self.service._execute(jobInfo) jobInfo.set_execution_end() - self.handle_threshold(self.service.get_threshold(), jobInfo.was_execution_successful()) + self.handle_threshold(jobInfo, self.service.get_threshold(), jobInfo.was_execution_successful()) self.log.d("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 8a498fa..86b1b66 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -27,21 +27,21 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("Could not create socket to host: " + jobInfo.get_host() + " on port: " + - str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("[tcpconnect] Could not create socket to host: " + jobInfo.get_host() + + " on port: " + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("Could not establish connection to host: " + jobInfo.get_host() + " on port: " + - str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("[tcpconnect] Could not establish connection to host: " + jobInfo.get_host() + + " on port: " + str(self.port) + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) jobInfo.set_errorcode(0) - jobInfo.set_message("Connection successful established to host: " + jobInfo.get_host() + " on port: " + - str(self.port)) + jobInfo.set_message("[tcpconnect] Connection successful established to host: " + jobInfo.get_host() + + " on port: " + str(self.port)) sock.close() diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py index fbee02d..ba258f3 100644 --- a/lib/tasks/jabber.py +++ b/lib/tasks/jabber.py @@ -17,10 +17,11 @@ class JabberTask(Task): self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - def execute(self, msg): - client = xmpp.Client('systemchaos.org') - client.connect(server=('systemchaos.org', 5222)) - client.auth('linspector', 'PASSWORD', 'alert') + def execute(self, msg, core): + #TODO: totally unstable just to use values from core. make checks before...! + client = xmpp.Client(core["tasks"]["jabber"]["host"]) + client.connect(server=(core["tasks"]["jabber"]["host"], core["tasks"]["jabber"]["port"])) + client.auth(core["tasks"]["jabber"]["username"], core["tasks"]["jabber"]["password"], 'alert') client.sendInitPresence() message = xmpp.Message(self.recipient, msg) message.setAttr('type', 'chat') diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index 177fe86..ca3280c 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -19,14 +19,14 @@ class MailTask(Task): self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - def execute(self, msg): + def execute(self, msg, core): message = MIMEText(msg) - message['Subject'] = 'Warning from Linspector' + message['Subject'] = msg now = datetime.datetime.now() message['Date'] = now.strftime("%a, %d %b %Y %H:%M:%S") - message['From'] = "warning@linspector.org" + message['From'] = core["tasks"]["mail"]["from"] message['To'] = self.recipient - s = smtplib.SMTP('localhost') + s = smtplib.SMTP(core["tasks"]["mail"]["host"], core["tasks"]["mail"]["port"]) s.sendmail("warning@linspector.org", self.recipient, message.as_string()) s.quit() diff --git a/linspector b/linspector index 22100c5..a3f63b4 100755 --- a/linspector +++ b/linspector @@ -67,7 +67,7 @@ def main(): for service in hostgroup.get_services(): for host in hostgroup.get_hosts(): for period in service.get_periods(): - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors()) + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) schedulerJob = period.createJob(scheduler, job, handleJob) if schedulerJob is not None: job.set_job(schedulerJob) From a0e76cc80a200830872ff180733271612e7b7d1c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 02:31:50 +0200 Subject: [PATCH 211/268] added some new stuff --- examples/linspector.json | 18 +++++++++++++++++- examples/minimal.json | 20 +++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/examples/linspector.json b/examples/linspector.json index b12465f..08c3764 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -188,9 +188,25 @@ } }, "core":{ + "instance_name": "Master Monitoring (monitor.example.org)", "max_logfile_size": 1024000, "max_logfile_count": 4, "max_worker_threads": 8, - "members":[ "root" ] + "members":[ "root" ], + "tasks":{ + "jabber":{ + "host": "example.org", + "port": 5222, + "username": "USERNAME", + "password": "PASSWORD" + }, + "mail":{ + "host": "localhost", + "port": 25, + "from": "linspector@example.org" + }, + "sms":{ + } + } } } \ No newline at end of file diff --git a/examples/minimal.json b/examples/minimal.json index 0453708..117b8d4 100644 --- a/examples/minimal.json +++ b/examples/minimal.json @@ -47,6 +47,24 @@ }, "layouts":{ "main":{"hostgroups": ["power_plant"], "enabled": true} + }, + "core":{ + "max_logfile_size": 1024000, + "max_logfile_count": 4, + "max_worker_threads": 8, + "members":[ "root" ], + "tasks":{ + "jabber":{ + "host": "systemchaos.org", + "port": 5222, + "username": "USERNAME", + "password": "PASSWORD" + }, + "mail":{ + "host": "localhost", + "port": 25, + "from": "linspector@systemchaos.org" + } + } } - } \ No newline at end of file From 67ad6acc20ca659ca91223cca0e2e5e17a61b597 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 20 Sep 2013 02:39:23 +0200 Subject: [PATCH 212/268] just some more core config stuff and disabled xmpp logging --- lib/tasks/jabber.py | 2 +- lib/tasks/mail.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py index ba258f3..a3bc4cd 100644 --- a/lib/tasks/jabber.py +++ b/lib/tasks/jabber.py @@ -19,7 +19,7 @@ class JabberTask(Task): def execute(self, msg, core): #TODO: totally unstable just to use values from core. make checks before...! - client = xmpp.Client(core["tasks"]["jabber"]["host"]) + client = xmpp.Client(core["tasks"]["jabber"]["host"], core["tasks"]["jabber"]["port"], None) client.connect(server=(core["tasks"]["jabber"]["host"], core["tasks"]["jabber"]["port"])) client.auth(core["tasks"]["jabber"]["username"], core["tasks"]["jabber"]["password"], 'alert') client.sendInitPresence() diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index ca3280c..4ed4aeb 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -15,7 +15,7 @@ class MailTask(Task): if not "type" in kwargs: raise Exception("'type' not in typeDict " + str(kwargs)) if not "args" in kwargs: - raise Exception("typeDict " + str(kwargs) + " has nor arguments!") + raise Exception("typeDict " + str(kwargs) + " has no arguments!") self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] @@ -27,7 +27,7 @@ class MailTask(Task): message['From'] = core["tasks"]["mail"]["from"] message['To'] = self.recipient s = smtplib.SMTP(core["tasks"]["mail"]["host"], core["tasks"]["mail"]["port"]) - s.sendmail("warning@linspector.org", self.recipient, message.as_string()) + s.sendmail(core["tasks"]["mail"]["from"], self.recipient, message.as_string()) s.quit() From 4b2513bfca874d32b6f93275e098bca9a4fd3ac2 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sat, 21 Sep 2013 04:44:01 +0200 Subject: [PATCH 213/268] just some housekeeping... :) i like! --- lib/config/parser.py | 24 ++++++++--------- lib/frontends/lish.py | 11 +++----- lib/tasks/mail.py | 1 + linspector | 63 +++++++++++++++++-------------------------- 4 files changed, 40 insertions(+), 59 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 71c062e..84dfb21 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -13,16 +13,16 @@ from lib.processors.processor import Processor from lib.parsers.parser import Parser from lib.tasks.task import Task -MOD_SERVICES = "services" -MOD_PROCESSORS = "processors" -MOD_PARSERS = "parsers" -MOD_TASKS = "tasks" +MOD_SERVICES = "services" +MOD_PROCESSORS = "processors" +MOD_PARSERS = "parsers" +MOD_TASKS = "tasks" -KEY_LAYOUTS = "layouts" -KEY_HOSTGROUPS = "hostgroups" -KEY_MEMBERS = "members" -KEY_PERIODS = "periods" -KEY_CORE = "core" +KEY_LAYOUTS = "layouts" +KEY_HOSTGROUPS = "hostgroups" +KEY_MEMBERS = "members" +KEY_PERIODS = "periods" +KEY_CORE = "core" class ConfigurationException(Exception): @@ -135,10 +135,10 @@ class ConfigParser: if class_check(item): repl.append(item) else: - self.log.w(" ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + self.log.w("Ignoring class " + clazzItem["class"] + "! It does not pass the class check!") except ImportError, err: - self.log.w("could not import " + clazz + ": " + str(clazzItem) + "! reason") + self.log.w("Could not import " + clazz + ": " + str(clazzItem) + "! reason") self.log.w(str(err)) except KeyError, k: self.log.w("Key " + str(k) + " not in classItem " + str(clazzItem)) @@ -202,8 +202,6 @@ class FullConfigParser(ConfigParser): """ self.jsonDict = self._read_json_config(configFilename) - - # first step creator = lambda name, values: Layout(name,**values) layouts = self._create_raw_Object(self.jsonDict[KEY_LAYOUTS], "Layout", creator) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 9fcf918..8d3e639 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -10,7 +10,7 @@ import os from shlex import split as shsplit from cmd import Cmd -VERSION = "0.1" +__version__ = "0.1" class LishFrontend(Frontend): @@ -23,7 +23,7 @@ class LishFrontend(Frontend): run = True while run: try: - commander.cmdloop("LISH - Linspector interactive shell") + commander.cmdloop("Lish - Linspector interactive shell (" + __version__ + ")") except KeyboardInterrupt, ki: run = False except Exception, err: @@ -80,7 +80,7 @@ class ShellCommander(CommandBase, object): os.system(text) def help_shell(self): - print("execute any shell command. Can also be achieved by a '!' postfix") + print("execute any shell command. Can also be achieved by a '!' prefix") def complete_shell(self, text, line, begidx, endidx): try: @@ -158,9 +158,6 @@ class LishCommander(Exit, ShellCommander, LogCommander): executes python using 'exec'. ''' - - - def help_hostgroup(self): print ''' usage: @@ -172,4 +169,4 @@ class LishCommander(Exit, ShellCommander, LogCommander): def complete_hostgroup(self, text, line, begidx, endidx): if begidx == 10: - return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs + return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs \ No newline at end of file diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index 4ed4aeb..81f780f 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -24,6 +24,7 @@ class MailTask(Task): message['Subject'] = msg now = datetime.datetime.now() message['Date'] = now.strftime("%a, %d %b %Y %H:%M:%S") + #TODO: totally unstable just to use values from core. make checks before...! message['From'] = core["tasks"]["mail"]["from"] message['To'] = self.recipient s = smtplib.SMTP(core["tasks"]["mail"]["host"], core["tasks"]["mail"]["port"]) diff --git a/linspector b/linspector index a3f63b4..6533020 100755 --- a/linspector +++ b/linspector @@ -1,12 +1,10 @@ #!/usr/bin/python2.7 -tt -__version__ = "0.5/TEKKEN" +__version__ = "0.6/TCPCONNECT" __default_config__ = "./examples/minimal.json" import argparse -import time import logging -import subprocess as sp from lib.core.logger import Logger from lib.frontends.lish import LishFrontend from lib.config.parser import FullConfigParser @@ -17,18 +15,15 @@ from lib.core.job import Job def parseArgs(): parser = argparse.ArgumentParser( description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", - epilog="linspector is not some program expecting computers to run!", + epilog="linspector is not some program expecting computers to run! Visit http://linspector.org for more " + "information.", prog="linspector") - parser.add_argument("action", choices=["start", "stop", "restart", "attach"], - help="defines if linspector should beeing attached, started, stopped or restarted.") parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) parser.add_argument("-c", "--config", default=__default_config__, help="select configfile to use") parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", help="set logfile to use") - parser.add_argument("-p", "--pidfile", default="./tmp/linspector.pid", metavar="FILE", - help="set the pidfile to use (default: /tmp/linspector.pid)") output = parser.add_mutually_exclusive_group() output.add_argument("-q", "--quiet", action="store_const", dest="loglevel", const=logging.ERROR, @@ -36,9 +31,9 @@ def parseArgs(): output.add_argument("-w", "--warning", action="store_const", dest="loglevel", const=logging.WARNING, help="output warnings") output.add_argument("-v", "--verbose", action="store_const", dest="loglevel", const=logging.INFO, - help="output infos") + help="output info messages") output.add_argument("-d", "--debug", action="store_const", dest="loglevel", const=logging.DEBUG, - help="output debug infos") + help="output debug messages") output.set_defaults(loglevel=logging.INFO) return parser.parse_args() @@ -53,40 +48,30 @@ def main(): log.i("parsed arguments") - if args.action == "start": - configParser = FullConfigParser(log) - linConf, core = configParser.parse_config(args.config) + configParser = FullConfigParser(log) + linConf, core = configParser.parse_config(args.config) - scheduler = Scheduler() + scheduler = Scheduler() - scheduler.start() - jobs = [] + scheduler.start() + jobs = [] - for layout in linConf.get_enabled_layouts(): - for hostgroup in layout.get_hostgroups(): - for service in hostgroup.get_services(): - for host in hostgroup.get_hosts(): - for period in service.get_periods(): - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) - schedulerJob = period.createJob(scheduler, job, handleJob) - if schedulerJob is not None: - job.set_job(schedulerJob) - job.set_logger(log) - jobs.append(job) + for layout in linConf.get_enabled_layouts(): + for hostgroup in layout.get_hostgroups(): + for service in hostgroup.get_services(): + for host in hostgroup.get_hosts(): + for period in service.get_periods(): + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) + schedulerJob = period.createJob(scheduler, job, handleJob) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(log) + jobs.append(job) - frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) + frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) - log.d("shutting down scheduler") - scheduler.shutdown(wait=False) - - elif args.action == "stop": - log.i("stopping linspector is currently unsupported") - elif args.action == "restart": - sp.call("./linspector stop") - sp.call( - "./linspector start --config " + args.config + " --logfile " + args.logfile + " --pidfile " + args.pidfile) - elif args.action == "attach": - log.i("attaching linspector is currently unsupported") + log.d("shutting down scheduler") + scheduler.shutdown(wait=False) log.close() From 9b38c424f87d7e8009383d2fbb029e95d23b099c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 23 Sep 2013 17:02:57 +0200 Subject: [PATCH 214/268] added the tweet task for alerting via twitter --- lib/tasks/tweet.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 lib/tasks/tweet.py diff --git a/lib/tasks/tweet.py b/lib/tasks/tweet.py new file mode 100644 index 0000000..c8a4234 --- /dev/null +++ b/lib/tasks/tweet.py @@ -0,0 +1,28 @@ +""" +The tweet/twitter task. +""" + +import twitter +from lib.tasks.task import Task + + +class TweetTask(Task): + def __init__(self, **kwargs): + if not "type" in kwargs: + raise Exception("'type' not in typeDict " + str(kwargs)) + if not "args" in kwargs: + raise Exception("typeDict " + str(kwargs) + " has no arguments!") + self.set_task_type(kwargs["type"]) + self.recipient = kwargs["args"]["rcpt"] + + def execute(self, msg): + api = twitter.Api(consumer_key='consumer_key', + consumer_secret='consumer_secret', + access_token_key='access_token', + access_token_secret='access_token_secret') + status = api.PostUpdate(msg) + pass + + +def create(taskDict): + return TweetTask(**taskDict) \ No newline at end of file From 4c40cbcfe928806ffdf9446030561cc241667c9a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 23 Sep 2013 22:43:06 +0200 Subject: [PATCH 215/268] this twitter stuff sucks. doesn't work actually --- lib/tasks/tweet.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/tasks/tweet.py b/lib/tasks/tweet.py index c8a4234..0c58fd2 100644 --- a/lib/tasks/tweet.py +++ b/lib/tasks/tweet.py @@ -1,8 +1,10 @@ """ The tweet/twitter task. + +Uses: tweepy """ -import twitter +import tweepy from lib.tasks.task import Task @@ -15,13 +17,11 @@ class TweetTask(Task): self.set_task_type(kwargs["type"]) self.recipient = kwargs["args"]["rcpt"] - def execute(self, msg): - api = twitter.Api(consumer_key='consumer_key', - consumer_secret='consumer_secret', - access_token_key='access_token', - access_token_secret='access_token_secret') - status = api.PostUpdate(msg) - pass + def execute(self, msg, core): + auth = tweepy.BasicAuthHandler("user", "pass") + api = tweepy.API(auth) + api.update_status(self.recipient) + print(self.get_task_type()) def create(taskDict): From 3aaaa5d56e6e4936accd44c00a62cb85eda27ec7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Mon, 23 Sep 2013 23:50:59 +0200 Subject: [PATCH 216/268] nothing done... just pass... ;) --- examples/hanez.json | 6 +++--- examples/linspector.json | 30 +++++++++++++++--------------- examples/minimal.json | 12 ++++++------ 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/hanez.json b/examples/hanez.json index 35ac11c..6291466 100644 --- a/examples/hanez.json +++ b/examples/hanez.json @@ -13,7 +13,7 @@ "hostgroups":{ "servers":{ "members": ["hanez"], - "hosts": [ "a.systemchaos.org", "b.systemchaos.org" ], + "hosts": [ "a.example.org", "b.example.org" ], "services":[ { "class": "tcpconnect", @@ -37,7 +37,7 @@ "members":[ "root" ], "tasks": { "jabber":{ - "host": "systemchaos.org", + "host": "example.org", "port": 5222, "username": "USERNAME", "password": "PASSWORD" @@ -45,7 +45,7 @@ "mail":{ "host": "localhost", "port": 25, - "from": "linspector@systemchaos.org" + "from": "linspector@example.org" } } } diff --git a/examples/linspector.json b/examples/linspector.json index 08c3764..84b2598 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -3,21 +3,21 @@ "root":{ "name": "Admin", "comment": "The Linspector Admin", - "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "admin@systems.hanez.org" }}, - { "class": "sms", "type": "critical", "args":{ "rcpt": "+49112" }}, - { "class": "jabber", "type": "critical", "args":{ "rcpt": "admin@jabber.hanez.org" }}] + "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "admin@example.org" }}, + { "class": "sms", "type": "critical", "args":{ "rcpt": "+491120000000000" }}, + { "class": "jabber", "type": "critical", "args":{ "rcpt": "admin@example.org" }}] }, "hanez":{ - "name": "Johannes Findeisen", + "name": "Hanez", "comment": "Just a nerd doing admin stuff.", "parent": "darth", - "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "you@hanez.org" }}, - { "class": "sms", "type": "critical", "args":{ "rcpt": "+49110" }}] + "tasks":[{ "class": "mail", "type": "warning", "args":{ "rcpt": "you@example.org" }}, + { "class": "sms", "type": "critical", "args":{ "rcpt": "+491100000000000" }}] }, "darth":{ "name": "Darth Vader", "comment": "The father", - "tasks":{ "class": "mail", "type": "warning", "args":{ "rcpt": "darth.vader@hanez.org" }} + "tasks":{ "class": "mail", "type": "warning", "args":{ "rcpt": "darth.vader@example.org" }} } }, "periods":{ @@ -30,20 +30,20 @@ "hostgroups":{ "group1":{ "members":[ "hanez" ], - "hosts":[ "a.systemchaos.org", "b.systemchaos.org" ], + "hosts":[ "a.example.org", "b.example.org" ], "parents":[ "network" ], "processors":[ { "class": "mongodb", - "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default" } + "args":{ "host": "mongodb.example.org", "user": "mongo", "password": "secret", "database": "default" } }, { "class": "syslog", - "args":{ "host": "syslog.linspector.org", "user": "syslog", "password": "secret" } + "args":{ "host": "syslog.example.org", "user": "syslog", "password": "secret" } }, { "class": "mariadb", - "args":{ "host": "mariadb.linspector.org", "port": "3306", "user": "maria", "password": "secret", "database": "linspector" } + "args":{ "host": "mariadb.example.org", "port": "3306", "user": "maria", "password": "secret", "database": "linspector" } } ], "services":[ @@ -88,7 +88,7 @@ }, "group2":{ "members":[ "hanez" ], - "hosts":["x.systemchaos.org", "y.systemchaos.org" ], + "hosts":["x.example.org", "y.example.org" ], "services":[ { "class": "ping", @@ -108,7 +108,7 @@ }, "group3":{ "members":[ "hanez" ], - "hosts":[ "master.systemchaos.org" ], + "hosts":[ "master.example.org" ], "services":[ { "class": "ssh", @@ -137,11 +137,11 @@ }, "network":{ "members":[ "hanez" ], - "hosts":[ "router.systemchaos.org" ], + "hosts":[ "router.example.org" ], "processors":[ { "class": "mongodb", - "args":{ "host": "mongodb.hanez.org", "user": "mongo", "password": "secret", "database": "default" } + "args":{ "host": "mongodb.example.org", "user": "mongo", "password": "secret", "database": "default" } } ], "services":[ diff --git a/examples/minimal.json b/examples/minimal.json index 117b8d4..715dcaa 100644 --- a/examples/minimal.json +++ b/examples/minimal.json @@ -4,8 +4,8 @@ "name": "Homer Simpson", "comment": "Security Inspector", "tasks": [ - {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}}, - {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@burnscorp.sp"}} + {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@example.sp"}}, + {"class":"mail", "type": "donut", "args": {"rcpt": "homer_j_simpson@example.sp"}} ] } }, @@ -17,9 +17,9 @@ "hostgroups":{ "power_plant":{ "members": ["homer"], - "hosts": ["powerplant.springfield.com"], + "hosts": ["powerplant.example.com"], "processors":[ - {"class": "mongodb", "args":{ "host": "mongodb.burnscorp.org", "user": "homer", "password": "useless", "database": "default" }} + {"class": "mongodb", "args":{ "host": "mongodb.example.org", "user": "homer", "password": "useless", "database": "default" }} ], "services":[ { @@ -55,7 +55,7 @@ "members":[ "root" ], "tasks":{ "jabber":{ - "host": "systemchaos.org", + "host": "example.org", "port": 5222, "username": "USERNAME", "password": "PASSWORD" @@ -63,7 +63,7 @@ "mail":{ "host": "localhost", "port": 25, - "from": "linspector@systemchaos.org" + "from": "linspector@example.org" } } } From 839b1f438c1c9160237c00950a2f0671c3e93c35 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 24 Sep 2013 00:01:52 +0200 Subject: [PATCH 217/268] added some content --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5f77cb0..d9050c7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ linspector ========== -A simple Linux based vital information monitoring solution +A simple, Python based, system & network vital information monitoring solution -Please visit http://linspector.org/ for more information. +Please visit http://linspector.org/ for more information. Much stuff there is outdated but we have redesigned a lot. + +The code is very simple and easy to understand, so take a look there if you are interested in Linspector. + +Linspector currently only supports a tcpconnect probe as a service to monitor. It support reporting via SMTP and XMPP. +Not more! + +For us it is great that the idea of that kind of software works perfectly using Python. Parsing the configuration file wasn't easy since Linspector objects are created dynamically from configuration. Scheduling of jobs is also done. We need to fix some bugs but when this is done we will start adding features to make Linspector usable in the wild. + +Linspector is licensed under the terms of the AGPL license. \ No newline at end of file From 3fa796e4c69ec0a8bfea0dc4b4325567ac45a31f Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 24 Sep 2013 00:17:44 +0200 Subject: [PATCH 218/268] hrhrhrhrhr, sounds better... ;) --- AUTHORS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 231f9a1..cd6c87f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Johannes Findeisen - Maintainer -Rafael Timmerberg - Maintainer +Johannes Findeisen - Core Developer +Rafael Timmerberg - Core Developer From 0c94c067f754379671037f0437432aba5abe43e5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 24 Sep 2013 00:24:40 +0200 Subject: [PATCH 219/268] some more content... --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d9050c7..6702a5f 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,22 @@ linspector ========== -A simple, Python based, system & network vital information monitoring solution +A simple, Python based, system & network vital information monitoring solution. Please visit http://linspector.org/ for more information. Much stuff there is outdated but we have redesigned a lot. The code is very simple and easy to understand, so take a look there if you are interested in Linspector. -Linspector currently only supports a tcpconnect probe as a service to monitor. It support reporting via SMTP and XMPP. -Not more! +Linspector currently only supports a "tcpconnect" probe on ports as a service to monitor. It supports reporting via SMTP and XMPP. Not more! -For us it is great that the idea of that kind of software works perfectly using Python. Parsing the configuration file wasn't easy since Linspector objects are created dynamically from configuration. Scheduling of jobs is also done. We need to fix some bugs but when this is done we will start adding features to make Linspector usable in the wild. +For us it is great that the idea of that kind of software works perfectly using Python. + +Parsing the configuration file wasn't easy since Linspector objects are being created dynamically from configuration. It works! + +Scheduling of jobs is also done. It works! + +We need to fix some bugs but when this is done we will start adding features to make Linspector usable in the wild. + +Next step will be business logic to manage an admins everyday monitoring tasks. SNMP will be added when the "tcpconnect" service works perfectly; Then some more services will be added too. We need the framework running first and then we will go on... ;) Linspector is licensed under the terms of the AGPL license. \ No newline at end of file From 3d63f4862154a1af9149d290867238b7fe4ea229 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 24 Sep 2013 00:30:12 +0200 Subject: [PATCH 220/268] just fixes... bla bla bla --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6702a5f..b665f1c 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,12 @@ Parsing the configuration file wasn't easy since Linspector objects are being cr Scheduling of jobs is also done. It works! +Alerting of jobs is partly done but: It works! + We need to fix some bugs but when this is done we will start adding features to make Linspector usable in the wild. Next step will be business logic to manage an admins everyday monitoring tasks. SNMP will be added when the "tcpconnect" service works perfectly; Then some more services will be added too. We need the framework running first and then we will go on... ;) +Since we are redesigning a lot off stuff from day to day it makes no sense to publish documentation. We are working on a small set of documents to make readers understand Linspector but for now there is no time for that. + Linspector is licensed under the terms of the AGPL license. \ No newline at end of file From 4048bc252eb2f95d89869e22b0affaa07777a6bb Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 25 Sep 2013 03:08:24 +0200 Subject: [PATCH 221/268] simplified logging. creates logging stuff in linspector now. no Logger class needed anymore. more advanced output in log message like filename,funcname,linenumber --- lib/config/parser.py | 16 ++++++++-------- lib/core/command.py | 6 +++--- lib/core/job.py | 10 +++++----- linspector | 41 +++++++++++++++++++++++++++++++++++------ 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/lib/config/parser.py b/lib/config/parser.py index 84dfb21..f711e50 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -71,7 +71,7 @@ class ConfigParser: with open(configFilename) as cfgFile: config = cfgFile.read() - self.log.i("reading Config: " + configFilename) + self.log.info("reading Config: " + configFilename) return json.loads(config) def _create_raw_Object(self, jsonDict, msgName, creator): @@ -90,8 +90,8 @@ class ConfigParser: item = creator(key, val) items.append(item) except Exception: - self.log.w("ignoring " + msgName + ": " + key + "! reason:") - self.log.w(str(Exception)) + self.log.warning("ignoring " + msgName + ": " + key + "! reason:") + self.log.warning(str(Exception)) return items def _load_module(self, clazz, modPart): @@ -135,15 +135,15 @@ class ConfigParser: if class_check(item): repl.append(item) else: - self.log.w("Ignoring class " + clazzItem["class"] + "! It does not pass the class check!") + self.log.warning("Ignoring class " + clazzItem["class"] + "! It does not pass the class check!") except ImportError, err: - self.log.w("Could not import " + clazz + ": " + str(clazzItem) + "! reason") - self.log.w(str(err)) + self.log.warning("Could not import " + clazz + ": " + str(clazzItem) + "! reason") + self.log.warning(str(err)) except KeyError, k: - self.log.w("Key " + str(k) + " not in classItem " + str(clazzItem)) + self.log.warning("Key " + str(k) + " not in classItem " + str(clazzItem)) except Exception, e: - self.log.w("Error while replacing class ( " + clazz + " ): " + str(e)) + self.log.warning("Error while replacing class ( " + clazz + " ): " + str(e)) del items[:] items.extend(repl) diff --git a/lib/core/command.py b/lib/core/command.py index e851038..d00b895 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -27,12 +27,12 @@ class Command: try: self.commandStart = dt.now() - self.log.i("calling command " + str(self.command) + " at " + str(self.commandStart)) + self.log.info("calling command " + str(self.command) + " at " + str(self.commandStart)) #self.output=sp.check_output(self.command.split()) process = Popen(self.command, stdout=sp.PIPE, stderr=sp.PIPE, shell=True) self.output, self.error = process.communicate() - self.log.d(str(self.output)) - self.log.d(str(self.error)) + self.log.debug(str(self.output)) + self.log.debug(str(self.error)) self.retcode = process.poll() except CalledProcessError: self.error = CalledProcessError.output diff --git a/lib/core/job.py b/lib/core/job.py index 6f8be0c..f159c88 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -40,7 +40,7 @@ class Job: self.jobThreshold += 1 if self.jobThreshold >= serviceThreshold: - self.log.d("Threshold reached!") + self.log.debug("Threshold reached!") self.handle_alarm(jobInfo, self.jobThreshold - serviceThreshold) def handle_alarm(self, jobInfo, thresholdOffset): @@ -49,8 +49,8 @@ class Job: task.execute(jobInfo.get_message(), self.core) def handle_call(self): - self.log.d("handle call") - self.log.d(self.service) + self.log.debug("handle call") + self.log.debug(self.service) try: jobInfo = JobInfo(self.host, self.service) self.service._execute(jobInfo) @@ -58,12 +58,12 @@ class Job: self.handle_threshold(jobInfo, self.service.get_threshold(), jobInfo.was_execution_successful()) - self.log.d("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) + self.log.debug("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) self.jobInfos.append(jobInfo) except Exception, e: - self.log.d(e) + self.log.debug(e) class JobInfo(object): diff --git a/linspector b/linspector index 6533020..0d51138 100755 --- a/linspector +++ b/linspector @@ -5,7 +5,10 @@ __default_config__ = "./examples/minimal.json" import argparse import logging -from lib.core.logger import Logger +import logging.handlers +import os +import os.path as path + from lib.frontends.lish import LishFrontend from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler @@ -38,15 +41,42 @@ def parseArgs(): return parser.parse_args() +def setup_logging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): + logfile = path.expanduser(logfile) + if not path.exists(path.dirname(logfile)): + os.makedirs(path.dirname(logfile)) + + log = logging.getLogger("LinspectorLogger") + log.setLevel(logging.DEBUG) + + consoleHandler = logging.StreamHandler() + consoleHandler.setLevel(logLevel) + + fileHandler = logging.handlers.RotatingFileHandler(logfile, maxBytes=1024000, backupCount=4) + fileHandler.setLevel(logfileLevel) + + consoleFormatter = logging.Formatter('[%(levelname)s]: %(message)s') + #TODO: if debug with file and function else without that + fileFormatter = logging.Formatter('%(asctime)s %(pathname)s %(module)s %(funcName)s %(lineno)d [%(levelname)s]: %(message)s') + + consoleHandler.setFormatter(consoleFormatter) + fileHandler.setFormatter(fileFormatter) + + log.addHandler(consoleHandler) + log.addHandler(fileHandler) + return log + + def handleJob(jobInfo): jobInfo.handle_call() def main(): args = parseArgs() - log = Logger(args.logfile, args.loglevel) + print args.logfile + log = setup_logging(args.logfile, args.loglevel) - log.i("parsed arguments") + log.info("parsed arguments") configParser = FullConfigParser(log) linConf, core = configParser.parse_config(args.config) @@ -70,11 +100,10 @@ def main(): frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) - log.d("shutting down scheduler") + log.debug("shutting down scheduler") + logging.shutdown() scheduler.shutdown(wait=False) - log.close() - if __name__ == "__main__": main() \ No newline at end of file From dbddbba4104fe73db96e4237f5a682b4ffc2eb3a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 25 Sep 2013 03:14:39 +0200 Subject: [PATCH 222/268] small cleanups --- linspector | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/linspector b/linspector index 0d51138..e4056ff 100755 --- a/linspector +++ b/linspector @@ -8,11 +8,10 @@ import logging import logging.handlers import os import os.path as path - -from lib.frontends.lish import LishFrontend -from lib.config.parser import FullConfigParser from apscheduler.scheduler import Scheduler +from lib.config.parser import FullConfigParser from lib.core.job import Job +from lib.frontends.lish import LishFrontend def parseArgs(): @@ -41,7 +40,7 @@ def parseArgs(): return parser.parse_args() -def setup_logging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): +def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): logfile = path.expanduser(logfile) if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) @@ -73,8 +72,8 @@ def handleJob(jobInfo): def main(): args = parseArgs() - print args.logfile - log = setup_logging(args.logfile, args.loglevel) + + log = setupLogging(args.logfile, args.loglevel) log.info("parsed arguments") From 09855d25815da2b9d8f81274877e2deedc729bf0 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 25 Sep 2013 03:33:43 +0200 Subject: [PATCH 223/268] we need to think about logging a bit... ;) look at the TODO in linspector. --- linspector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linspector b/linspector index e4056ff..daae320 100755 --- a/linspector +++ b/linspector @@ -72,7 +72,7 @@ def handleJob(jobInfo): def main(): args = parseArgs() - + #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging log = setupLogging(args.logfile, args.loglevel) log.info("parsed arguments") @@ -101,7 +101,7 @@ def main(): log.debug("shutting down scheduler") logging.shutdown() - scheduler.shutdown(wait=False) + scheduler.shutdown(wait=True) if __name__ == "__main__": From 73cb75ee0bf85fe85ac6e6b28d19cb69a9e0024c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 25 Sep 2013 03:44:04 +0200 Subject: [PATCH 224/268] added TODO --- linspector | 1 + 1 file changed, 1 insertion(+) diff --git a/linspector b/linspector index daae320..0e5053a 100755 --- a/linspector +++ b/linspector @@ -22,6 +22,7 @@ def parseArgs(): prog="linspector") parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) + #TODO: make the config file a required field without -c or --config at the end eg: linspector config.json parser.add_argument("-c", "--config", default=__default_config__, help="select configfile to use") parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", From 88b396f0f9d9f6e014f42981e15a1bafd17ddd84 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Wed, 25 Sep 2013 04:18:55 +0200 Subject: [PATCH 225/268] added login to smtp server --- lib/tasks/mail.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index 81f780f..60c11e4 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -28,6 +28,7 @@ class MailTask(Task): message['From'] = core["tasks"]["mail"]["from"] message['To'] = self.recipient s = smtplib.SMTP(core["tasks"]["mail"]["host"], core["tasks"]["mail"]["port"]) + s.login(core["tasks"]["mail"]["username"], core["tasks"]["mail"]["password"]) s.sendmail(core["tasks"]["mail"]["from"], self.recipient, message.as_string()) s.quit() From 0ec9c51418c180ee7a97bec64d71cad1f0fa080d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 01:29:09 +0200 Subject: [PATCH 226/268] added title to docs in makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8d023c2..1026145 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ clean: find . -type f -name "*.pyc" -exec rm -f {} \; docs: - epydoc --html -o docs . + epydoc -n "Linspector Monitoring - API Documentation" --html -o docs . docs-pdf: - epydoc --pdf -o docs . + epydoc -n "Linspector Monitoring - API Documentation" --pdf -o docs . docs-clean: rm -rf docs From 5661fe9d5c92aa3706208a04f30cc7b6621e3470 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 01:44:35 +0200 Subject: [PATCH 227/268] added templates --- examples/linspector.json | 8 ++------ examples/minimal.json | 13 +++++++++---- templates/services/snmpget_linux_load.json | 8 ++++++++ templates/services/tcpconnect_80.json | 6 ++++++ 4 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 templates/services/snmpget_linux_load.json create mode 100644 templates/services/tcpconnect_80.json diff --git a/examples/linspector.json b/examples/linspector.json index 84b2598..e92ca28 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -156,12 +156,8 @@ "args":{ "line": 2, "col": 8 }} }, { - "class": "snmpget", - "comment": "The Linux system load", - "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, - "fails":{ "warning": 4.00, "critical": 8.00 }, - "periods":[ "middle" ], - "threshold": 10 + "template": "snmpget_linux_load", + "fails":{ "warning": 2.00, "critical": 4.00 } }, { "class": "snmpget", diff --git a/examples/minimal.json b/examples/minimal.json index 715dcaa..8f7e3a4 100644 --- a/examples/minimal.json +++ b/examples/minimal.json @@ -29,10 +29,10 @@ "threshold": 50 }, { - "class": "ping", - "fails": {"donut": 1000}, - "periods": ["doh"], - "threshold": 100 + "class": "ping", + "fails": {"donut": 1000}, + "periods": ["doh"], + "threshold": 100 }, { "class": "tcpconnect", @@ -41,6 +41,11 @@ "fails": {"donut": 0}, "threshold": 0, "comment": "my personal reminder, hehe" + }, + { + "template": "tcpconnect_80", + "threshold": 10, + "periods": ["moes_time"], } ] } diff --git a/templates/services/snmpget_linux_load.json b/templates/services/snmpget_linux_load.json new file mode 100644 index 0000000..85b3341 --- /dev/null +++ b/templates/services/snmpget_linux_load.json @@ -0,0 +1,8 @@ +{ + "class": "snmpget", + "comment": "The Linux system load", + "args":{ "port": 161, "community": "linspector", "oid": ".1.3.6.1.4.1.2021.10.1.3.1" }, + "fails":{ "warning": 4.00, "critical": 8.00 }, + "periods":[ "normal" ], + "threshold": 10 +} \ No newline at end of file diff --git a/templates/services/tcpconnect_80.json b/templates/services/tcpconnect_80.json new file mode 100644 index 0000000..ec711a2 --- /dev/null +++ b/templates/services/tcpconnect_80.json @@ -0,0 +1,6 @@ +{ + "class": "tcpconnect", + "args": { "port": 80 }, + "periods": ["normal"], + "threshold": 10 +} \ No newline at end of file From f7b2eab4f98f26290441087b6db4a842fe302823 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 02:03:14 +0200 Subject: [PATCH 228/268] just added __name__ to the logger --- linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector b/linspector index 0e5053a..bbe46d9 100755 --- a/linspector +++ b/linspector @@ -46,7 +46,7 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfile if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) - log = logging.getLogger("LinspectorLogger") + log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) consoleHandler = logging.StreamHandler() From 033af959a60380674b06c9286186c5d0b84981b5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 04:10:20 +0200 Subject: [PATCH 229/268] added mail adresses to AUTHORS --- AUTHORS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index cd6c87f..541f17b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,2 +1,2 @@ -Johannes Findeisen - Core Developer -Rafael Timmerberg - Core Developer +Johannes Findeisen - Core Developer +Rafael Timmerberg - Core Developer \ No newline at end of file From df3b22a308c67cd8ed87206f7d604f427f1c2850 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 04:31:06 +0200 Subject: [PATCH 230/268] edited title for docs in makefile --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1026145..c1b218a 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ clean: find . -type f -name "*.pyc" -exec rm -f {} \; docs: - epydoc -n "Linspector Monitoring - API Documentation" --html -o docs . + epydoc -n "Linspector - API Documentation" --html -o docs . docs-pdf: - epydoc -n "Linspector Monitoring - API Documentation" --pdf -o docs . + epydoc -n "Linspector - API Documentation" --pdf -o docs . docs-clean: rm -rf docs From c0ddae7eb549802fe04af3681adfae9a742d81ab Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 06:17:08 +0200 Subject: [PATCH 231/268] moved some frontends/* to new backends/; backends are threads running in background, no frontend --- lib/{frontends => backends}/https.py | 6 +++--- lib/{frontends => backends}/xmpp.py | 4 ++-- lib/frontends/frontend.py | 7 +++---- linspector | 8 ++++++++ 4 files changed, 16 insertions(+), 9 deletions(-) rename lib/{frontends => backends}/https.py (61%) rename lib/{frontends => backends}/xmpp.py (79%) diff --git a/lib/frontends/https.py b/lib/backends/https.py similarity index 61% rename from lib/frontends/https.py rename to lib/backends/https.py index 70a63dd..89811ad 100644 --- a/lib/frontends/https.py +++ b/lib/backends/https.py @@ -1,13 +1,13 @@ """ -A HTTPS frontend to the current Linspector instance. +A HTTPS backend to the current Linspector instance. A Webserver listening for requests to give information about the internal state of linspector. (maybe providing a JSON API to the instance too...) """ -from lib.frontends.frontend import Frontend +from lib.backends.backend import Backend -class HttpsFrontend(Frontend): +class HttpsBackend(Backend): def __init__(self, **kwargs): return \ No newline at end of file diff --git a/lib/frontends/xmpp.py b/lib/backends/xmpp.py similarity index 79% rename from lib/frontends/xmpp.py rename to lib/backends/xmpp.py index 6b84397..c1d25dc 100644 --- a/lib/frontends/xmpp.py +++ b/lib/backends/xmpp.py @@ -5,9 +5,9 @@ Just for the fun in it... Linspector connects to a XMPP Server and are accepting give back information. The Linspector admin client will then be any Jabber Client... ;) """ -from lib.frontends.frontend import Frontend +from lib.backends.backend import Backend -class XmmpFrontend(Frontend): +class XmmpBackend(Backend): def __init__(self, **kwargs): pass \ No newline at end of file diff --git a/lib/frontends/frontend.py b/lib/frontends/frontend.py index f953f25..91ff5b3 100644 --- a/lib/frontends/frontend.py +++ b/lib/frontends/frontend.py @@ -1,9 +1,8 @@ """ -Just the frontends.py stub... ;) +Frontends are GUI interfaces to Linspector. This could be a shell or other terminal based GUI. -If linspector is being started without a frontend "enabled" it just is doing stuff like: polling, alerting, logging etc. - -Frontends are absolutely no requirement for running Linspector. +Frontends are absolutely no requirement for running Linspector. If no frontend is selected Linspector will just log +stuff to stdout. """ diff --git a/linspector b/linspector index bbe46d9..458bc0f 100755 --- a/linspector +++ b/linspector @@ -11,6 +11,7 @@ import os.path as path from apscheduler.scheduler import Scheduler from lib.config.parser import FullConfigParser from lib.core.job import Job +from lib.backends.https import HttpsBackend from lib.frontends.lish import LishFrontend @@ -98,6 +99,13 @@ def main(): job.set_logger(log) jobs.append(job) + #TODO: Load Backend Threads here before initializing the frontend. + ''' + for backend in backends.enabled + backend.start + + take care of signals etc. to sthutdown the threads when stopping linspector. + ''' frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) log.debug("shutting down scheduler") From a26797946578fb4f6b53538bd843573e26cc3a9c Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 06:17:44 +0200 Subject: [PATCH 232/268] forgot two files in backends --- lib/backends/__init__.py | 0 lib/backends/backend.py | 11 +++++++++++ 2 files changed, 11 insertions(+) create mode 100644 lib/backends/__init__.py create mode 100644 lib/backends/backend.py diff --git a/lib/backends/__init__.py b/lib/backends/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/backends/backend.py b/lib/backends/backend.py new file mode 100644 index 0000000..507331c --- /dev/null +++ b/lib/backends/backend.py @@ -0,0 +1,11 @@ +""" +Backends can be a http service or xml-rpc service; let's say background threads providing an interface somewhere. They +should run as background threads. + +Backends are absolutely no requirement for running Linspector. +""" + + +class Backend(): + def __init__(self, **kwargs): + return \ No newline at end of file From 8905be422867c559bc33d2eee025b20e5fc51faa Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 06:20:48 +0200 Subject: [PATCH 233/268] added TODO to job --- lib/core/job.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/core/job.py b/lib/core/job.py index f159c88..4b88c1b 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -45,6 +45,7 @@ class Job: def handle_alarm(self, jobInfo, thresholdOffset): for member in self.service.get_hostgroup().get_members(): + #TODO: Put Tasks in a run queue and execute them in a background thread. FIFO! Reduces delay in core. for task in member.get_tasks(): task.execute(jobInfo.get_message(), self.core) From 9c4b253704d6dbffc169b0f5bd9f1e0bb8833cab Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 1 Oct 2013 06:51:54 +0200 Subject: [PATCH 234/268] added interface class to core for backend/frontend commnication to core --- lib/core/interface.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 lib/core/interface.py diff --git a/lib/core/interface.py b/lib/core/interface.py new file mode 100644 index 0000000..26a7d88 --- /dev/null +++ b/lib/core/interface.py @@ -0,0 +1,8 @@ +""" +The interface class should contain all stuff for frontend/backend communication to the Linspector core. +""" + + +class Interface(): + def __init__(self): + pass From 8467bbb74ce748743ebb6d819f08591a9643ac42 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 4 Oct 2013 18:01:22 +0200 Subject: [PATCH 235/268] just playing with jobs in lish... ;) --- lib/frontends/lish.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 8d3e639..8b91de9 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -153,6 +153,14 @@ class LishCommander(Exit, ShellCommander, LogCommander): def do_python(self, text): exec text + def do_jobs(self, text): + if text == "list": + for job in self._scheduler.get_jobs(): + print job + + def help_jobs(self): + print "Job helper functions" + def help_python(self): print ''' executes python using 'exec'. From 9e21d5f87e4693a8ecfcb3b380db0c63ebe1bcca Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 4 Oct 2013 18:38:02 +0200 Subject: [PATCH 236/268] added own scheduler class for extending apscheduler --- lib/core/scheduler.py | 7 +++++++ linspector | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 lib/core/scheduler.py diff --git a/lib/core/scheduler.py b/lib/core/scheduler.py new file mode 100644 index 0000000..6cee297 --- /dev/null +++ b/lib/core/scheduler.py @@ -0,0 +1,7 @@ + +from apscheduler.scheduler import Scheduler + + +class Scheduler(Scheduler): + def test(self): + pass \ No newline at end of file diff --git a/linspector b/linspector index 458bc0f..4b696b7 100755 --- a/linspector +++ b/linspector @@ -8,9 +8,10 @@ import logging import logging.handlers import os import os.path as path -from apscheduler.scheduler import Scheduler + from lib.config.parser import FullConfigParser from lib.core.job import Job +from lib.core.scheduler import Scheduler from lib.backends.https import HttpsBackend from lib.frontends.lish import LishFrontend From 4571e52cde1e29e6600da8b519668f10c86b245d Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 00:08:47 +0200 Subject: [PATCH 237/268] added license header to all code files --- lib/backends/backend.py | 17 +++++++++++++++++ lib/backends/https.py | 17 +++++++++++++++++ lib/backends/xmpp.py | 17 +++++++++++++++++ lib/config/config.py | 17 +++++++++++++++++ lib/config/hostgroups.py | 20 ++++++++++++++++++++ lib/config/layouts.py | 20 ++++++++++++++++++++ lib/config/members.py | 19 +++++++++++++++++++ lib/config/parser.py | 20 ++++++++++++++++++++ lib/config/periods.py | 21 +++++++++++++++++++++ lib/core/command.py | 19 +++++++++++++++++++ lib/core/daemon.py | 20 ++++++++++++++++++++ lib/core/interface.py | 17 +++++++++++++++++ lib/core/job.py | 17 +++++++++++++++++ lib/core/linspector_daemon.py | 19 +++++++++++++++++++ lib/core/logger.py | 19 +++++++++++++++++++ lib/core/scheduler.py | 18 ++++++++++++++++++ lib/frontends/frontend.py | 17 +++++++++++++++++ lib/frontends/lish.py | 17 +++++++++++++++++ lib/parsers/parser.py | 20 ++++++++++++++++++++ lib/parsers/shell.py | 19 +++++++++++++++++++ lib/processors/mariadb.py | 17 +++++++++++++++++ lib/processors/mongodb.py | 17 +++++++++++++++++ lib/processors/processor.py | 17 +++++++++++++++++ lib/processors/syslog.py | 17 +++++++++++++++++ lib/services/http.py | 17 +++++++++++++++++ lib/services/ping.py | 17 +++++++++++++++++ lib/services/service.py | 18 ++++++++++++++++++ lib/services/shell.py | 17 +++++++++++++++++ lib/services/snmpget.py | 17 +++++++++++++++++ lib/services/ssh.py | 17 +++++++++++++++++ lib/services/tcpconnect.py | 17 +++++++++++++++++ lib/tasks/jabber.py | 17 +++++++++++++++++ lib/tasks/mail.py | 19 ++++++++++++++++++- lib/tasks/sms.py | 17 +++++++++++++++++ lib/tasks/task.py | 17 +++++++++++++++++ lib/tasks/tweet.py | 17 +++++++++++++++++ linspector | 19 +++++++++++++++++++ 37 files changed, 663 insertions(+), 1 deletion(-) diff --git a/lib/backends/backend.py b/lib/backends/backend.py index 507331c..89e6f68 100644 --- a/lib/backends/backend.py +++ b/lib/backends/backend.py @@ -3,6 +3,23 @@ Backends can be a http service or xml-rpc service; let's say background threads should run as background threads. Backends are absolutely no requirement for running Linspector. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/backends/https.py b/lib/backends/https.py index 89811ad..9e71203 100644 --- a/lib/backends/https.py +++ b/lib/backends/https.py @@ -3,6 +3,23 @@ A HTTPS backend to the current Linspector instance. A Webserver listening for requests to give information about the internal state of linspector. (maybe providing a JSON API to the instance too...) + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.backends.backend import Backend diff --git a/lib/backends/xmpp.py b/lib/backends/xmpp.py index c1d25dc..88853af 100644 --- a/lib/backends/xmpp.py +++ b/lib/backends/xmpp.py @@ -3,6 +3,23 @@ The Linspector XMPP Frontend... Just for the fun in it... Linspector connects to a XMPP Server and are accepting commands from special users and can give back information. The Linspector admin client will then be any Jabber Client... ;) + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.backends.backend import Backend diff --git a/lib/config/config.py b/lib/config/config.py index 0ea9beb..bcefe8a 100644 --- a/lib/config/config.py +++ b/lib/config/config.py @@ -1,5 +1,22 @@ """ The LinspectorConfig class. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/config/hostgroups.py b/lib/config/hostgroups.py index 047bf13..4cc8175 100644 --- a/lib/config/hostgroups.py +++ b/lib/config/hostgroups.py @@ -1,3 +1,23 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + + class HostGroupException(Exception): def __init__(self, msg): self.msg = msg diff --git a/lib/config/layouts.py b/lib/config/layouts.py index a12affb..52da1c0 100644 --- a/lib/config/layouts.py +++ b/lib/config/layouts.py @@ -1,3 +1,23 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + + class LayoutException(Exception): def __init__(self, msg): self.msg = msg diff --git a/lib/config/members.py b/lib/config/members.py index f028c96..334405b 100644 --- a/lib/config/members.py +++ b/lib/config/members.py @@ -1,3 +1,22 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + import re diff --git a/lib/config/parser.py b/lib/config/parser.py index f711e50..12fdca7 100644 --- a/lib/config/parser.py +++ b/lib/config/parser.py @@ -1,7 +1,27 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + from os.path import isfile from os.path import join import json import imp + from layouts import Layout from hostgroups import HostGroup from members import Member diff --git a/lib/config/periods.py b/lib/config/periods.py index 22c8140..cb94577 100644 --- a/lib/config/periods.py +++ b/lib/config/periods.py @@ -1,3 +1,24 @@ +""" + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + + class Period(object): def __init__(self, name): self.name = name diff --git a/lib/core/command.py b/lib/core/command.py index d00b895..18e3ec3 100644 --- a/lib/core/command.py +++ b/lib/core/command.py @@ -1,3 +1,22 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + import subprocess as sp from subprocess import Popen from subprocess import CalledProcessError diff --git a/lib/core/daemon.py b/lib/core/daemon.py index 1b85f42..c80bb2d 100644 --- a/lib/core/daemon.py +++ b/lib/core/daemon.py @@ -1,3 +1,23 @@ +""" + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + import sys import os import time diff --git a/lib/core/interface.py b/lib/core/interface.py index 26a7d88..c2457d6 100644 --- a/lib/core/interface.py +++ b/lib/core/interface.py @@ -1,5 +1,22 @@ """ The interface class should contain all stuff for frontend/backend communication to the Linspector core. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/core/job.py b/lib/core/job.py index 4b88c1b..3743556 100644 --- a/lib/core/job.py +++ b/lib/core/job.py @@ -1,6 +1,23 @@ """ This is what job_function needs as parameter for each job to successfully execute. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from datetime import datetime diff --git a/lib/core/linspector_daemon.py b/lib/core/linspector_daemon.py index cfdd8c4..2e01f10 100644 --- a/lib/core/linspector_daemon.py +++ b/lib/core/linspector_daemon.py @@ -1,3 +1,22 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + from ..core import logger from ..core.daemon import Daemon diff --git a/lib/core/logger.py b/lib/core/logger.py index 9acc559..087f992 100644 --- a/lib/core/logger.py +++ b/lib/core/logger.py @@ -1,3 +1,22 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + import logging import logging.handlers import os diff --git a/lib/core/scheduler.py b/lib/core/scheduler.py index 6cee297..b5ccb79 100644 --- a/lib/core/scheduler.py +++ b/lib/core/scheduler.py @@ -1,3 +1,21 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" from apscheduler.scheduler import Scheduler diff --git a/lib/frontends/frontend.py b/lib/frontends/frontend.py index 91ff5b3..42d58e0 100644 --- a/lib/frontends/frontend.py +++ b/lib/frontends/frontend.py @@ -3,6 +3,23 @@ Frontends are GUI interfaces to Linspector. This could be a shell or other termi Frontends are absolutely no requirement for running Linspector. If no frontend is selected Linspector will just log stuff to stdout. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/frontends/lish.py b/lib/frontends/lish.py index 8b91de9..5f1f11b 100644 --- a/lib/frontends/lish.py +++ b/lib/frontends/lish.py @@ -2,6 +2,23 @@ Lish is the Linspector Interactive Shell... This will become a commandline interface to Linspector. Think of a network switch or router like those from Cisco. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/parsers/parser.py b/lib/parsers/parser.py index 8ba3028..2a81437 100644 --- a/lib/parsers/parser.py +++ b/lib/parsers/parser.py @@ -1,3 +1,23 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + + class Parser: def __init__(self, **kwargs): pass diff --git a/lib/parsers/shell.py b/lib/parsers/shell.py index c767cb3..5c7ec91 100644 --- a/lib/parsers/shell.py +++ b/lib/parsers/shell.py @@ -1,3 +1,22 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + from lib.parsers.parser import Parser diff --git a/lib/processors/mariadb.py b/lib/processors/mariadb.py index 2d09875..e31e94e 100644 --- a/lib/processors/mariadb.py +++ b/lib/processors/mariadb.py @@ -1,5 +1,22 @@ """ The MariaDB processor + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.processors.processor import Processor diff --git a/lib/processors/mongodb.py b/lib/processors/mongodb.py index 52ba222..b5cbe0f 100644 --- a/lib/processors/mongodb.py +++ b/lib/processors/mongodb.py @@ -1,5 +1,22 @@ """ The MongoDB processor + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.processors.processor import Processor diff --git a/lib/processors/processor.py b/lib/processors/processor.py index 08d5c88..787cfb1 100644 --- a/lib/processors/processor.py +++ b/lib/processors/processor.py @@ -1,5 +1,22 @@ """ The processor class for postprocessing polled data. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/processors/syslog.py b/lib/processors/syslog.py index be5c0cf..5060188 100644 --- a/lib/processors/syslog.py +++ b/lib/processors/syslog.py @@ -1,5 +1,22 @@ """ The syslog processor + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.processors.processor import Processor diff --git a/lib/services/http.py b/lib/services/http.py index 6e8dfda..b9db8ef 100644 --- a/lib/services/http.py +++ b/lib/services/http.py @@ -6,6 +6,23 @@ content could be fetched and compared.HTTPS is not validating the server certifi This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and not use a parser. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import urllib diff --git a/lib/services/ping.py b/lib/services/ping.py index d123ae0..b102869 100644 --- a/lib/services/ping.py +++ b/lib/services/ping.py @@ -1,5 +1,22 @@ """ The ping service in pure Python. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ # http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ diff --git a/lib/services/service.py b/lib/services/service.py index d1540e4..f6459af 100644 --- a/lib/services/service.py +++ b/lib/services/service.py @@ -1,3 +1,21 @@ +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" KEY_PARSER = "parser" KEY_COMMENT = "comment" diff --git a/lib/services/shell.py b/lib/services/shell.py index 65878fb..26512a6 100644 --- a/lib/services/shell.py +++ b/lib/services/shell.py @@ -1,5 +1,22 @@ """ The shell service. This is for executing local shell commands and retrieve the output. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.services.service import Service diff --git a/lib/services/snmpget.py b/lib/services/snmpget.py index ec07b3f..dc59827 100644 --- a/lib/services/snmpget.py +++ b/lib/services/snmpget.py @@ -1,5 +1,22 @@ """ The snmpget service in pure Python. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ #from pysnmp.entity.rfc3413.oneliner import cmdgen diff --git a/lib/services/ssh.py b/lib/services/ssh.py index 7bc083e..3ce2766 100644 --- a/lib/services/ssh.py +++ b/lib/services/ssh.py @@ -2,6 +2,23 @@ The ssh service This is for executing remote shell commands and retrieve the output. This service is using paramiko (http://www.lag.net/paramiko/). + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import paramiko diff --git a/lib/services/tcpconnect.py b/lib/services/tcpconnect.py index 86b1b66..d1edf38 100644 --- a/lib/services/tcpconnect.py +++ b/lib/services/tcpconnect.py @@ -3,6 +3,23 @@ The tcpconnect service. This is to check if a service on a specific port is reac This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and not use a parser. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import socket diff --git a/lib/tasks/jabber.py b/lib/tasks/jabber.py index a3bc4cd..f1e9476 100644 --- a/lib/tasks/jabber.py +++ b/lib/tasks/jabber.py @@ -2,6 +2,23 @@ The Jabber (XMPP) task. Uses: http://xmpppy.sourceforge.net/ + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import xmpp diff --git a/lib/tasks/mail.py b/lib/tasks/mail.py index 60c11e4..5551c2f 100644 --- a/lib/tasks/mail.py +++ b/lib/tasks/mail.py @@ -1,7 +1,24 @@ """ The mail task. -http://docs.python.org/2/library/email-examples.html +http://docs.python.org/2/library/email-examples.html# + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import datetime diff --git a/lib/tasks/sms.py b/lib/tasks/sms.py index 203ab4d..79d07dd 100644 --- a/lib/tasks/sms.py +++ b/lib/tasks/sms.py @@ -1,5 +1,22 @@ """ The sms task. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ from lib.tasks.task import Task diff --git a/lib/tasks/task.py b/lib/tasks/task.py index cf88f03..5085e00 100644 --- a/lib/tasks/task.py +++ b/lib/tasks/task.py @@ -1,5 +1,22 @@ """ The task class. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ diff --git a/lib/tasks/tweet.py b/lib/tasks/tweet.py index 0c58fd2..388c7c2 100644 --- a/lib/tasks/tweet.py +++ b/lib/tasks/tweet.py @@ -2,6 +2,23 @@ The tweet/twitter task. Uses: tweepy + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . """ import tweepy diff --git a/linspector b/linspector index 4b696b7..8ba8a1d 100755 --- a/linspector +++ b/linspector @@ -1,5 +1,24 @@ #!/usr/bin/python2.7 -tt +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + __version__ = "0.6/TCPCONNECT" __default_config__ = "./examples/minimal.json" From 161110f0898854182ca613f896da5f5d9af8528a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 21:10:55 +0200 Subject: [PATCH 238/268] added json rpc backend for adding an interface to GUI applications --- lib/backends/jsonrpc.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/backends/jsonrpc.py diff --git a/lib/backends/jsonrpc.py b/lib/backends/jsonrpc.py new file mode 100644 index 0000000..e25cd47 --- /dev/null +++ b/lib/backends/jsonrpc.py @@ -0,0 +1,27 @@ +""" +A JSON-RPC backend using HTTP. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + +from lib.backends.backend import Backend + + +class JsonrpcBackend(Backend): + def __init__(self, **kwargs): + return \ No newline at end of file From ac12a06607e734cfb07602ec920edd834e62ee60 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 21:12:08 +0200 Subject: [PATCH 239/268] added some config stub --- examples/linspector.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/linspector.json b/examples/linspector.json index e92ca28..e904615 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -189,6 +189,11 @@ "max_logfile_count": 4, "max_worker_threads": 8, "members":[ "root" ], + "backends": { + "jsonrpc": { + "port": "2323" + } + }, "tasks":{ "jabber":{ "host": "example.org", From 3f592b61c0d0715fde21f0d9b069c07c732dc03a Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 21:21:37 +0200 Subject: [PATCH 240/268] small config update just to not forget the idea --- examples/linspector.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/linspector.json b/examples/linspector.json index e904615..a19b6a6 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -191,7 +191,10 @@ "members":[ "root" ], "backends": { "jsonrpc": { - "port": "2323" + "listen": "127.0.0.1", + "port": "2323", + "username": "linspector", + "password": "linspector" } }, "tasks":{ From b73d0abb2d2034ac91788f0f3bd27aab62939823 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 22:16:31 +0200 Subject: [PATCH 241/268] moved linspector to bin and renamed lib --- linspector | 137 ------------------ {lib/backends => linspector}/__init__.py | 0 .../backends}/__init__.py | 0 {lib => linspector}/backends/backend.py | 0 {lib => linspector}/backends/https.py | 2 +- {lib => linspector}/backends/jsonrpc.py | 2 +- {lib => linspector}/backends/xmpp.py | 2 +- {lib/core => linspector/config}/__init__.py | 0 {lib => linspector}/config/config.py | 0 {lib => linspector}/config/hostgroups.py | 0 {lib => linspector}/config/layouts.py | 0 {lib => linspector}/config/members.py | 0 {lib => linspector}/config/parser.py | 10 +- {lib => linspector}/config/periods.py | 0 .../frontends => linspector/core}/__init__.py | 0 {lib => linspector}/core/command.py | 0 {lib => linspector}/core/daemon.py | 0 {lib => linspector}/core/interface.py | 0 {lib => linspector}/core/job.py | 0 {lib => linspector}/core/linspector_daemon.py | 2 +- {lib => linspector}/core/logger.py | 0 {lib => linspector}/core/scheduler.py | 0 .../frontends}/__init__.py | 0 {lib => linspector}/frontends/frontend.py | 0 {lib => linspector}/frontends/lish.py | 2 +- .../parsers}/__init__.py | 0 {lib => linspector}/parsers/parser.py | 0 {lib => linspector}/parsers/shell.py | 2 +- .../processors}/__init__.py | 0 {lib => linspector}/processors/mariadb.py | 2 +- {lib => linspector}/processors/mongodb.py | 2 +- {lib => linspector}/processors/processor.py | 0 {lib => linspector}/processors/syslog.py | 2 +- .../tasks => linspector/services}/__init__.py | 0 {lib => linspector}/services/http.py | 2 +- {lib => linspector}/services/ping.py | 2 +- {lib => linspector}/services/service.py | 0 {lib => linspector}/services/shell.py | 2 +- {lib => linspector}/services/snmpget.py | 2 +- {lib => linspector}/services/ssh.py | 2 +- {lib => linspector}/services/tcpconnect.py | 2 +- linspector/tasks/__init__.py | 0 {lib => linspector}/tasks/jabber.py | 2 +- {lib => linspector}/tasks/mail.py | 2 +- {lib => linspector}/tasks/sms.py | 2 +- {lib => linspector}/tasks/task.py | 0 {lib => linspector}/tasks/tweet.py | 2 +- 47 files changed, 24 insertions(+), 161 deletions(-) delete mode 100755 linspector rename {lib/backends => linspector}/__init__.py (100%) rename {lib/config => linspector/backends}/__init__.py (100%) rename {lib => linspector}/backends/backend.py (100%) rename {lib => linspector}/backends/https.py (95%) rename {lib => linspector}/backends/jsonrpc.py (94%) rename {lib => linspector}/backends/xmpp.py (95%) rename {lib/core => linspector/config}/__init__.py (100%) rename {lib => linspector}/config/config.py (100%) rename {lib => linspector}/config/hostgroups.py (100%) rename {lib => linspector}/config/layouts.py (100%) rename {lib => linspector}/config/members.py (100%) rename {lib => linspector}/config/parser.py (97%) rename {lib => linspector}/config/periods.py (100%) rename {lib/frontends => linspector/core}/__init__.py (100%) rename {lib => linspector}/core/command.py (100%) rename {lib => linspector}/core/daemon.py (100%) rename {lib => linspector}/core/interface.py (100%) rename {lib => linspector}/core/job.py (100%) rename {lib => linspector}/core/linspector_daemon.py (96%) rename {lib => linspector}/core/logger.py (100%) rename {lib => linspector}/core/scheduler.py (100%) rename {lib/parsers => linspector/frontends}/__init__.py (100%) rename {lib => linspector}/frontends/frontend.py (100%) rename {lib => linspector}/frontends/lish.py (99%) rename {lib/processors => linspector/parsers}/__init__.py (100%) rename {lib => linspector}/parsers/parser.py (100%) rename {lib => linspector}/parsers/shell.py (95%) rename {lib/services => linspector/processors}/__init__.py (100%) rename {lib => linspector}/processors/mariadb.py (94%) rename {lib => linspector}/processors/mongodb.py (94%) rename {lib => linspector}/processors/processor.py (100%) rename {lib => linspector}/processors/syslog.py (94%) rename {lib/tasks => linspector/services}/__init__.py (100%) rename {lib => linspector}/services/http.py (97%) rename {lib => linspector}/services/ping.py (99%) rename {lib => linspector}/services/service.py (100%) rename {lib => linspector}/services/shell.py (96%) rename {lib => linspector}/services/snmpget.py (97%) rename {lib => linspector}/services/ssh.py (97%) rename {lib => linspector}/services/tcpconnect.py (98%) create mode 100644 linspector/tasks/__init__.py rename {lib => linspector}/tasks/jabber.py (97%) rename {lib => linspector}/tasks/mail.py (98%) rename {lib => linspector}/tasks/sms.py (96%) rename {lib => linspector}/tasks/task.py (100%) rename {lib => linspector}/tasks/tweet.py (97%) diff --git a/linspector b/linspector deleted file mode 100755 index 8ba8a1d..0000000 --- a/linspector +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/python2.7 -tt - -""" -Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" - -This file is part of Linspector (http://linspector.org). - -Linspector is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -This program 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -""" - -__version__ = "0.6/TCPCONNECT" -__default_config__ = "./examples/minimal.json" - -import argparse -import logging -import logging.handlers -import os -import os.path as path - -from lib.config.parser import FullConfigParser -from lib.core.job import Job -from lib.core.scheduler import Scheduler -from lib.backends.https import HttpsBackend -from lib.frontends.lish import LishFrontend - - -def parseArgs(): - parser = argparse.ArgumentParser( - description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", - epilog="linspector is not some program expecting computers to run! Visit http://linspector.org for more " - "information.", - prog="linspector") - - parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) - #TODO: make the config file a required field without -c or --config at the end eg: linspector config.json - parser.add_argument("-c", "--config", default=__default_config__, - help="select configfile to use") - parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", - help="set logfile to use") - - output = parser.add_mutually_exclusive_group() - output.add_argument("-q", "--quiet", action="store_const", dest="loglevel", const=logging.ERROR, - help="output only errors") - output.add_argument("-w", "--warning", action="store_const", dest="loglevel", const=logging.WARNING, - help="output warnings") - output.add_argument("-v", "--verbose", action="store_const", dest="loglevel", const=logging.INFO, - help="output info messages") - output.add_argument("-d", "--debug", action="store_const", dest="loglevel", const=logging.DEBUG, - help="output debug messages") - output.set_defaults(loglevel=logging.INFO) - return parser.parse_args() - - -def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): - logfile = path.expanduser(logfile) - if not path.exists(path.dirname(logfile)): - os.makedirs(path.dirname(logfile)) - - log = logging.getLogger(__name__) - log.setLevel(logging.DEBUG) - - consoleHandler = logging.StreamHandler() - consoleHandler.setLevel(logLevel) - - fileHandler = logging.handlers.RotatingFileHandler(logfile, maxBytes=1024000, backupCount=4) - fileHandler.setLevel(logfileLevel) - - consoleFormatter = logging.Formatter('[%(levelname)s]: %(message)s') - #TODO: if debug with file and function else without that - fileFormatter = logging.Formatter('%(asctime)s %(pathname)s %(module)s %(funcName)s %(lineno)d [%(levelname)s]: %(message)s') - - consoleHandler.setFormatter(consoleFormatter) - fileHandler.setFormatter(fileFormatter) - - log.addHandler(consoleHandler) - log.addHandler(fileHandler) - return log - - -def handleJob(jobInfo): - jobInfo.handle_call() - - -def main(): - args = parseArgs() - #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging - log = setupLogging(args.logfile, args.loglevel) - - log.info("parsed arguments") - - configParser = FullConfigParser(log) - linConf, core = configParser.parse_config(args.config) - - scheduler = Scheduler() - - scheduler.start() - jobs = [] - - for layout in linConf.get_enabled_layouts(): - for hostgroup in layout.get_hostgroups(): - for service in hostgroup.get_services(): - for host in hostgroup.get_hosts(): - for period in service.get_periods(): - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) - schedulerJob = period.createJob(scheduler, job, handleJob) - if schedulerJob is not None: - job.set_job(schedulerJob) - job.set_logger(log) - jobs.append(job) - - #TODO: Load Backend Threads here before initializing the frontend. - ''' - for backend in backends.enabled - backend.start - - take care of signals etc. to sthutdown the threads when stopping linspector. - ''' - frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) - - log.debug("shutting down scheduler") - logging.shutdown() - scheduler.shutdown(wait=True) - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/lib/backends/__init__.py b/linspector/__init__.py similarity index 100% rename from lib/backends/__init__.py rename to linspector/__init__.py diff --git a/lib/config/__init__.py b/linspector/backends/__init__.py similarity index 100% rename from lib/config/__init__.py rename to linspector/backends/__init__.py diff --git a/lib/backends/backend.py b/linspector/backends/backend.py similarity index 100% rename from lib/backends/backend.py rename to linspector/backends/backend.py diff --git a/lib/backends/https.py b/linspector/backends/https.py similarity index 95% rename from lib/backends/https.py rename to linspector/backends/https.py index 9e71203..f8faf20 100644 --- a/lib/backends/https.py +++ b/linspector/backends/https.py @@ -22,7 +22,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.backends.backend import Backend +from linspector.backends.backend import Backend class HttpsBackend(Backend): diff --git a/lib/backends/jsonrpc.py b/linspector/backends/jsonrpc.py similarity index 94% rename from lib/backends/jsonrpc.py rename to linspector/backends/jsonrpc.py index e25cd47..54ac2be 100644 --- a/lib/backends/jsonrpc.py +++ b/linspector/backends/jsonrpc.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.backends.backend import Backend +from linspector.backends.backend import Backend class JsonrpcBackend(Backend): diff --git a/lib/backends/xmpp.py b/linspector/backends/xmpp.py similarity index 95% rename from lib/backends/xmpp.py rename to linspector/backends/xmpp.py index 88853af..ad852ba 100644 --- a/lib/backends/xmpp.py +++ b/linspector/backends/xmpp.py @@ -22,7 +22,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.backends.backend import Backend +from linspector.backends.backend import Backend class XmmpBackend(Backend): diff --git a/lib/core/__init__.py b/linspector/config/__init__.py similarity index 100% rename from lib/core/__init__.py rename to linspector/config/__init__.py diff --git a/lib/config/config.py b/linspector/config/config.py similarity index 100% rename from lib/config/config.py rename to linspector/config/config.py diff --git a/lib/config/hostgroups.py b/linspector/config/hostgroups.py similarity index 100% rename from lib/config/hostgroups.py rename to linspector/config/hostgroups.py diff --git a/lib/config/layouts.py b/linspector/config/layouts.py similarity index 100% rename from lib/config/layouts.py rename to linspector/config/layouts.py diff --git a/lib/config/members.py b/linspector/config/members.py similarity index 100% rename from lib/config/members.py rename to linspector/config/members.py diff --git a/lib/config/parser.py b/linspector/config/parser.py similarity index 97% rename from lib/config/parser.py rename to linspector/config/parser.py index 12fdca7..bf5f675 100644 --- a/lib/config/parser.py +++ b/linspector/config/parser.py @@ -28,10 +28,10 @@ from members import Member from config import LinspectorConfig from periods import CronPeriod, DatePeriod, IntervalPeriod -from lib.services.service import Service -from lib.processors.processor import Processor -from lib.parsers.parser import Parser -from lib.tasks.task import Task +from linspector.services.service import Service +from linspector.processors.processor import Processor +from linspector.parsers.parser import Parser +from linspector.tasks.task import Task MOD_SERVICES = "services" MOD_PROCESSORS = "processors" @@ -127,7 +127,7 @@ class ConfigParser: return mods[clazz] else: #mod = __import__(clazz) - p = join("lib", modPart, clazz + ".py") + p = join("linspector", modPart, clazz + ".py") mod = imp.load_source(clazz, p) mods[clazz] = mod return mod diff --git a/lib/config/periods.py b/linspector/config/periods.py similarity index 100% rename from lib/config/periods.py rename to linspector/config/periods.py diff --git a/lib/frontends/__init__.py b/linspector/core/__init__.py similarity index 100% rename from lib/frontends/__init__.py rename to linspector/core/__init__.py diff --git a/lib/core/command.py b/linspector/core/command.py similarity index 100% rename from lib/core/command.py rename to linspector/core/command.py diff --git a/lib/core/daemon.py b/linspector/core/daemon.py similarity index 100% rename from lib/core/daemon.py rename to linspector/core/daemon.py diff --git a/lib/core/interface.py b/linspector/core/interface.py similarity index 100% rename from lib/core/interface.py rename to linspector/core/interface.py diff --git a/lib/core/job.py b/linspector/core/job.py similarity index 100% rename from lib/core/job.py rename to linspector/core/job.py diff --git a/lib/core/linspector_daemon.py b/linspector/core/linspector_daemon.py similarity index 96% rename from lib/core/linspector_daemon.py rename to linspector/core/linspector_daemon.py index 2e01f10..ee9d940 100644 --- a/lib/core/linspector_daemon.py +++ b/linspector/core/linspector_daemon.py @@ -22,7 +22,7 @@ from ..core.daemon import Daemon """ TODO: Think about, that daemonizing this software is not our goal but when we want to that, this needs a rewrite and -should maybe move over to the daemon frontend. daemon.py will remain the the base for this and should stay in lib/core . +should maybe move over to the daemon frontend. daemon.py will remain the the base for this and should stay in linspector/core . Since a daemon it normally not a frontend we should think about how to handle this. When daemonizing a real frontend like "Lish" will make no sense but a frontend like "https" or "xmpp" could be useful anyway... """ diff --git a/lib/core/logger.py b/linspector/core/logger.py similarity index 100% rename from lib/core/logger.py rename to linspector/core/logger.py diff --git a/lib/core/scheduler.py b/linspector/core/scheduler.py similarity index 100% rename from lib/core/scheduler.py rename to linspector/core/scheduler.py diff --git a/lib/parsers/__init__.py b/linspector/frontends/__init__.py similarity index 100% rename from lib/parsers/__init__.py rename to linspector/frontends/__init__.py diff --git a/lib/frontends/frontend.py b/linspector/frontends/frontend.py similarity index 100% rename from lib/frontends/frontend.py rename to linspector/frontends/frontend.py diff --git a/lib/frontends/lish.py b/linspector/frontends/lish.py similarity index 99% rename from lib/frontends/lish.py rename to linspector/frontends/lish.py index 5f1f11b..4861cf0 100644 --- a/lib/frontends/lish.py +++ b/linspector/frontends/lish.py @@ -22,7 +22,7 @@ along with this program. If not, see . """ -from lib.frontends.frontend import Frontend +from linspector.frontends.frontend import Frontend import os from shlex import split as shsplit from cmd import Cmd diff --git a/lib/processors/__init__.py b/linspector/parsers/__init__.py similarity index 100% rename from lib/processors/__init__.py rename to linspector/parsers/__init__.py diff --git a/lib/parsers/parser.py b/linspector/parsers/parser.py similarity index 100% rename from lib/parsers/parser.py rename to linspector/parsers/parser.py diff --git a/lib/parsers/shell.py b/linspector/parsers/shell.py similarity index 95% rename from lib/parsers/shell.py rename to linspector/parsers/shell.py index 5c7ec91..3218e2d 100644 --- a/lib/parsers/shell.py +++ b/linspector/parsers/shell.py @@ -17,7 +17,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.parsers.parser import Parser +from linspector.parsers.parser import Parser class ShellParser(Parser): diff --git a/lib/services/__init__.py b/linspector/processors/__init__.py similarity index 100% rename from lib/services/__init__.py rename to linspector/processors/__init__.py diff --git a/lib/processors/mariadb.py b/linspector/processors/mariadb.py similarity index 94% rename from lib/processors/mariadb.py rename to linspector/processors/mariadb.py index e31e94e..5f92d9e 100644 --- a/lib/processors/mariadb.py +++ b/linspector/processors/mariadb.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.processors.processor import Processor +from linspector.processors.processor import Processor class MariadbProcessor(Processor): diff --git a/lib/processors/mongodb.py b/linspector/processors/mongodb.py similarity index 94% rename from lib/processors/mongodb.py rename to linspector/processors/mongodb.py index b5cbe0f..5d127cf 100644 --- a/lib/processors/mongodb.py +++ b/linspector/processors/mongodb.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.processors.processor import Processor +from linspector.processors.processor import Processor class MongodbProcessor(Processor): diff --git a/lib/processors/processor.py b/linspector/processors/processor.py similarity index 100% rename from lib/processors/processor.py rename to linspector/processors/processor.py diff --git a/lib/processors/syslog.py b/linspector/processors/syslog.py similarity index 94% rename from lib/processors/syslog.py rename to linspector/processors/syslog.py index 5060188..01fc7ad 100644 --- a/lib/processors/syslog.py +++ b/linspector/processors/syslog.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.processors.processor import Processor +from linspector.processors.processor import Processor class SyslogProcessor(Processor): diff --git a/lib/tasks/__init__.py b/linspector/services/__init__.py similarity index 100% rename from lib/tasks/__init__.py rename to linspector/services/__init__.py diff --git a/lib/services/http.py b/linspector/services/http.py similarity index 97% rename from lib/services/http.py rename to linspector/services/http.py index b9db8ef..7986370 100644 --- a/lib/services/http.py +++ b/linspector/services/http.py @@ -26,7 +26,7 @@ along with this program. If not, see . """ import urllib -from lib.services.service import Service +from linspector.services.service import Service class HttpService(Service): diff --git a/lib/services/ping.py b/linspector/services/ping.py similarity index 99% rename from lib/services/ping.py rename to linspector/services/ping.py index b102869..e85230f 100644 --- a/lib/services/ping.py +++ b/linspector/services/ping.py @@ -20,7 +20,7 @@ along with this program. If not, see . """ # http://code.activestate.com/recipes/409689-icmplib-library-for-creating-and-reading-icmp-pack/ -from lib.services.service import Service +from linspector.services.service import Service import struct diff --git a/lib/services/service.py b/linspector/services/service.py similarity index 100% rename from lib/services/service.py rename to linspector/services/service.py diff --git a/lib/services/shell.py b/linspector/services/shell.py similarity index 96% rename from lib/services/shell.py rename to linspector/services/shell.py index 26512a6..d840b1c 100644 --- a/lib/services/shell.py +++ b/linspector/services/shell.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.services.service import Service +from linspector.services.service import Service class ShellService(Service): diff --git a/lib/services/snmpget.py b/linspector/services/snmpget.py similarity index 97% rename from lib/services/snmpget.py rename to linspector/services/snmpget.py index dc59827..776efae 100644 --- a/lib/services/snmpget.py +++ b/linspector/services/snmpget.py @@ -20,7 +20,7 @@ along with this program. If not, see . """ #from pysnmp.entity.rfc3413.oneliner import cmdgen -from lib.services.service import Service +from linspector.services.service import Service class SnmpgetService(Service): diff --git a/lib/services/ssh.py b/linspector/services/ssh.py similarity index 97% rename from lib/services/ssh.py rename to linspector/services/ssh.py index 3ce2766..9b30ae1 100644 --- a/lib/services/ssh.py +++ b/linspector/services/ssh.py @@ -24,7 +24,7 @@ along with this program. If not, see . import paramiko import pprint import os -from lib.services.service import Service +from linspector.services.service import Service class SshService(Service): diff --git a/lib/services/tcpconnect.py b/linspector/services/tcpconnect.py similarity index 98% rename from lib/services/tcpconnect.py rename to linspector/services/tcpconnect.py index d1edf38..63bb028 100644 --- a/lib/services/tcpconnect.py +++ b/linspector/services/tcpconnect.py @@ -23,7 +23,7 @@ along with this program. If not, see . """ import socket -from lib.services.service import Service +from linspector.services.service import Service class TcpconnectService(Service): diff --git a/linspector/tasks/__init__.py b/linspector/tasks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/tasks/jabber.py b/linspector/tasks/jabber.py similarity index 97% rename from lib/tasks/jabber.py rename to linspector/tasks/jabber.py index f1e9476..cf1bc86 100644 --- a/lib/tasks/jabber.py +++ b/linspector/tasks/jabber.py @@ -22,7 +22,7 @@ along with this program. If not, see . """ import xmpp -from lib.tasks.task import Task +from linspector.tasks.task import Task class JabberTask(Task): diff --git a/lib/tasks/mail.py b/linspector/tasks/mail.py similarity index 98% rename from lib/tasks/mail.py rename to linspector/tasks/mail.py index 5551c2f..bd7f617 100644 --- a/lib/tasks/mail.py +++ b/linspector/tasks/mail.py @@ -24,7 +24,7 @@ along with this program. If not, see . import datetime import smtplib from email.mime.text import MIMEText -from lib.tasks.task import Task +from linspector.tasks.task import Task class MailTask(Task): diff --git a/lib/tasks/sms.py b/linspector/tasks/sms.py similarity index 96% rename from lib/tasks/sms.py rename to linspector/tasks/sms.py index 79d07dd..a5fd66a 100644 --- a/lib/tasks/sms.py +++ b/linspector/tasks/sms.py @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -from lib.tasks.task import Task +from linspector.tasks.task import Task class SmsTask(Task): diff --git a/lib/tasks/task.py b/linspector/tasks/task.py similarity index 100% rename from lib/tasks/task.py rename to linspector/tasks/task.py diff --git a/lib/tasks/tweet.py b/linspector/tasks/tweet.py similarity index 97% rename from lib/tasks/tweet.py rename to linspector/tasks/tweet.py index 388c7c2..68bf5ed 100644 --- a/lib/tasks/tweet.py +++ b/linspector/tasks/tweet.py @@ -22,7 +22,7 @@ along with this program. If not, see . """ import tweepy -from lib.tasks.task import Task +from linspector.tasks.task import Task class TweetTask(Task): From 0dbac62c5ce3442ad98798835da8381283f4cb43 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 22:16:46 +0200 Subject: [PATCH 242/268] moved linspector to bin and renamed lib --- {lib => bin}/__init__.py | 0 bin/linspector | 137 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) rename {lib => bin}/__init__.py (100%) create mode 100755 bin/linspector diff --git a/lib/__init__.py b/bin/__init__.py similarity index 100% rename from lib/__init__.py rename to bin/__init__.py diff --git a/bin/linspector b/bin/linspector new file mode 100755 index 0000000..334e09a --- /dev/null +++ b/bin/linspector @@ -0,0 +1,137 @@ +#!/usr/bin/python2.7 -tt + +""" +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + +__version__ = "0.6/TCPCONNECT" +__default_config__ = "./examples/minimal.json" + +import argparse +import logging +import logging.handlers +import os +import os.path as path + +from linspector.config.parser import FullConfigParser +from linspector.core.job import Job +from linspector.core.scheduler import Scheduler +from linspector.backends.https import HttpsBackend +from linspector.frontends.lish import LishFrontend + + +def parseArgs(): + parser = argparse.ArgumentParser( + description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", + epilog="linspector is not some program expecting computers to run! Visit http://linspector.org for more " + "information.", + prog="linspector") + + parser.add_argument("--version", action="version", version="%(prog)s " + str(__version__)) + #TODO: make the config file a required field without -c or --config at the end eg: linspector config.json + parser.add_argument("-c", "--config", default=__default_config__, + help="select configfile to use") + parser.add_argument("-l", "--logfile", default="./log/linspector.log", metavar="FILE", + help="set logfile to use") + + output = parser.add_mutually_exclusive_group() + output.add_argument("-q", "--quiet", action="store_const", dest="loglevel", const=logging.ERROR, + help="output only errors") + output.add_argument("-w", "--warning", action="store_const", dest="loglevel", const=logging.WARNING, + help="output warnings") + output.add_argument("-v", "--verbose", action="store_const", dest="loglevel", const=logging.INFO, + help="output info messages") + output.add_argument("-d", "--debug", action="store_const", dest="loglevel", const=logging.DEBUG, + help="output debug messages") + output.set_defaults(loglevel=logging.INFO) + return parser.parse_args() + + +def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): + logfile = path.expanduser(logfile) + if not path.exists(path.dirname(logfile)): + os.makedirs(path.dirname(logfile)) + + log = logging.getLogger(__name__) + log.setLevel(logging.DEBUG) + + consoleHandler = logging.StreamHandler() + consoleHandler.setLevel(logLevel) + + fileHandler = logging.handlers.RotatingFileHandler(logfile, maxBytes=1024000, backupCount=4) + fileHandler.setLevel(logfileLevel) + + consoleFormatter = logging.Formatter('[%(levelname)s]: %(message)s') + #TODO: if debug with file and function else without that + fileFormatter = logging.Formatter('%(asctime)s %(pathname)s %(module)s %(funcName)s %(lineno)d [%(levelname)s]: %(message)s') + + consoleHandler.setFormatter(consoleFormatter) + fileHandler.setFormatter(fileFormatter) + + log.addHandler(consoleHandler) + log.addHandler(fileHandler) + return log + + +def handleJob(jobInfo): + jobInfo.handle_call() + + +def main(): + args = parseArgs() + #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging + log = setupLogging(args.logfile, args.loglevel) + + log.info("parsed arguments") + + configParser = FullConfigParser(log) + linConf, core = configParser.parse_config(args.config) + + scheduler = Scheduler() + + scheduler.start() + jobs = [] + + for layout in linConf.get_enabled_layouts(): + for hostgroup in layout.get_hostgroups(): + for service in hostgroup.get_services(): + for host in hostgroup.get_hosts(): + for period in service.get_periods(): + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) + schedulerJob = period.createJob(scheduler, job, handleJob) + if schedulerJob is not None: + job.set_job(schedulerJob) + job.set_logger(log) + jobs.append(job) + + #TODO: Load Backend Threads here before initializing the frontend. + ''' + for backend in backends.enabled + backend.start + + take care of signals etc. to sthutdown the threads when stopping linspector. + ''' + frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) + + log.debug("shutting down scheduler") + logging.shutdown() + scheduler.shutdown(wait=True) + + +if __name__ == "__main__": + main() \ No newline at end of file From 0d472665b97e29cdfbb654062c6e045aa2451ee8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 22:23:08 +0200 Subject: [PATCH 243/268] typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b665f1c..19bfbe2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -linspector +Linspector ========== A simple, Python based, system & network vital information monitoring solution. From 025238dbbc70b3a80381c03f6a39d3d380c80325 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 22:24:11 +0200 Subject: [PATCH 244/268] cleanup; deleted senseless newlines --- LICENSE | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index a871fcf..2def0e8 100644 --- a/LICENSE +++ b/LICENSE @@ -658,5 +658,4 @@ specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see -. - +. \ No newline at end of file From 08a0ed137fbb31f4afa2d8eb12276e606b0d7462 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 22:27:37 +0200 Subject: [PATCH 245/268] added stub for a configfile validation tool --- bin/checkconfig | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100755 bin/checkconfig diff --git a/bin/checkconfig b/bin/checkconfig new file mode 100755 index 0000000..597f3c0 --- /dev/null +++ b/bin/checkconfig @@ -0,0 +1,22 @@ +#!/usr/bin/python2.7 -tt + +""" +Config file validator. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" \ No newline at end of file From 157de0cbd431d4ab02bdcd997f0a4b24ea6851b1 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 8 Oct 2013 23:00:44 +0200 Subject: [PATCH 246/268] typo fix --- examples/linspector.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/linspector.json b/examples/linspector.json index a19b6a6..790cdcb 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -191,7 +191,7 @@ "members":[ "root" ], "backends": { "jsonrpc": { - "listen": "127.0.0.1", + "host": "127.0.0.1", "port": "2323", "username": "linspector", "password": "linspector" From 0bfb8ef3ae3d8717c4571d591dcddc392f4bb340 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 10 Oct 2013 21:46:29 +0200 Subject: [PATCH 247/268] pretty job string function for lish, fixed logging TODO: set Logging levels --- bin/linspector | 6 ++++-- linspector/config/parser.py | 2 +- linspector/core/job.py | 14 ++++++++++++++ linspector/frontends/lish.py | 6 +++--- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/bin/linspector b/bin/linspector index 334e09a..0f08cfc 100755 --- a/bin/linspector +++ b/bin/linspector @@ -62,13 +62,14 @@ def parseArgs(): return parser.parse_args() -def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfileLevel=logging.DEBUG): +def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfileLevel=logging.DEBUG): logfile = path.expanduser(logfile) if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) + logging.basicConfig(level=logging.CRITICAL) log = logging.getLogger(__name__) - log.setLevel(logging.DEBUG) + #log.setLevel(logging.) consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logLevel) @@ -76,6 +77,7 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.DEBUG, logfile fileHandler = logging.handlers.RotatingFileHandler(logfile, maxBytes=1024000, backupCount=4) fileHandler.setLevel(logfileLevel) + consoleFormatter = logging.Formatter('[%(levelname)s]: %(message)s') #TODO: if debug with file and function else without that fileFormatter = logging.Formatter('%(asctime)s %(pathname)s %(module)s %(funcName)s %(lineno)d [%(levelname)s]: %(message)s') diff --git a/linspector/config/parser.py b/linspector/config/parser.py index bf5f675..4e193b8 100644 --- a/linspector/config/parser.py +++ b/linspector/config/parser.py @@ -47,7 +47,7 @@ KEY_CORE = "core" class ConfigurationException(Exception): def __init__(self, msg, log): - log.e(msg) + log.error(msg) self.msg = msg def __str__(self): diff --git a/linspector/core/job.py b/linspector/core/job.py index 3743556..616d84c 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -21,6 +21,7 @@ along with this program. If not, see . """ from datetime import datetime +from binascii import crc32 def generateId(): @@ -43,9 +44,22 @@ class Job: def __str__(self): return str(self.__dict__) + + def __hex__(self): + return hex(crc32(str(self.service) + str(self.host) + str(self.members))) + def set_logger(self, log): self.log = log + + + def pretty_string(self): + ret = self.__hex__() + if ret[0] == "-": + ret = ret[1:] + ret += ": (" + str(self.host) + str(self.service) + str(self.job) + ")" + return ret[2:] + def set_job(self, job): self.job = job diff --git a/linspector/frontends/lish.py b/linspector/frontends/lish.py index 4861cf0..ffc89af 100644 --- a/linspector/frontends/lish.py +++ b/linspector/frontends/lish.py @@ -164,7 +164,7 @@ class LishCommander(Exit, ShellCommander, LogCommander): try: hgCommander = HostgroupCommander(hg) hgCommander.cmdloop("Entering Hostmode of " + hgName + ":\n") - except KeyboardInterrupt, ke: + except KeyboardInterrupt, key: pass def do_python(self, text): @@ -172,8 +172,8 @@ class LishCommander(Exit, ShellCommander, LogCommander): def do_jobs(self, text): if text == "list": - for job in self._scheduler.get_jobs(): - print job + for job in self._jobs: + print job.pretty_string() def help_jobs(self): print "Job helper functions" From d885e699baf06f79a1e75381c932c69976ddcb97 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 10 Oct 2013 21:59:33 +0200 Subject: [PATCH 248/268] set jobHex to jobInfo --- linspector/core/job.py | 9 ++++----- linspector/services/tcpconnect.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/linspector/core/job.py b/linspector/core/job.py index 616d84c..ed9064f 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -51,12 +51,10 @@ class Job: def set_logger(self, log): self.log = log - - def pretty_string(self): ret = self.__hex__() if ret[0] == "-": - ret = ret[1:] + ret = "0" + ret[1:] ret += ": (" + str(self.host) + str(self.service) + str(self.job) + ")" return ret[2:] @@ -84,7 +82,7 @@ class Job: self.log.debug("handle call") self.log.debug(self.service) try: - jobInfo = JobInfo(self.host, self.service) + jobInfo = JobInfo(self.__hex__(), self.host, self.service) self.service._execute(jobInfo) jobInfo.set_execution_end() @@ -99,8 +97,9 @@ class Job: class JobInfo(object): - def __init__(self, host, service): + def __init__(self,jobHex, host, service): self.id = generateId() + self.jobHex = jobHex self.host = host self.service = service self.executionBegin = datetime.now() diff --git a/linspector/services/tcpconnect.py b/linspector/services/tcpconnect.py index 63bb028..2bfcf70 100644 --- a/linspector/services/tcpconnect.py +++ b/linspector/services/tcpconnect.py @@ -44,7 +44,7 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("[tcpconnect] Could not create socket to host: " + jobInfo.get_host() + + jobInfo.set_message("[tcpconnect: " + jobInfo.jobHex + "] Could not create socket to host: " + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") try: From 8a3379f7e301b0bee16fcbd5c3d7051a17b91897 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 10 Oct 2013 22:07:21 +0200 Subject: [PATCH 249/268] set global loglevel to debug --- bin/linspector | 2 +- linspector/core/job.py | 6 ++++-- linspector/services/service.py | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/bin/linspector b/bin/linspector index 0f08cfc..e1ef723 100755 --- a/bin/linspector +++ b/bin/linspector @@ -69,7 +69,7 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfile logging.basicConfig(level=logging.CRITICAL) log = logging.getLogger(__name__) - #log.setLevel(logging.) + log.setLevel(logging.DEBUG) consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logLevel) diff --git a/linspector/core/job.py b/linspector/core/job.py index ed9064f..e539466 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -54,9 +54,11 @@ class Job: def pretty_string(self): ret = self.__hex__() if ret[0] == "-": - ret = "0" + ret[1:] + ret = ret[3:] + else: + ret = ret[2:] ret += ": (" + str(self.host) + str(self.service) + str(self.job) + ")" - return ret[2:] + return ret def set_job(self, job): self.job = job diff --git a/linspector/services/service.py b/linspector/services/service.py index f6459af..af4b220 100644 --- a/linspector/services/service.py +++ b/linspector/services/service.py @@ -124,6 +124,8 @@ class Service(object): self._threshold -= 1 raise e + + def execute(self, jobInfo): pass From 14ad51741e0378526ac9a4407b49b1a2a6e554d9 Mon Sep 17 00:00:00 2001 From: "Rafael.Timmerberg" Date: Thu, 10 Oct 2013 22:24:05 +0200 Subject: [PATCH 250/268] added hexstring --- bin/linspector | 4 ++-- linspector/core/job.py | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bin/linspector b/bin/linspector index e1ef723..38359bb 100755 --- a/bin/linspector +++ b/bin/linspector @@ -67,9 +67,9 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfile if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) - logging.basicConfig(level=logging.CRITICAL) + logging.basicConfig(level=logging.WARNING) log = logging.getLogger(__name__) - log.setLevel(logging.DEBUG) + #log.setLevel(logging.ERROR) consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logLevel) diff --git a/linspector/core/job.py b/linspector/core/job.py index e539466..fc49733 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -48,18 +48,22 @@ class Job: def __hex__(self): return hex(crc32(str(self.service) + str(self.host) + str(self.members))) - def set_logger(self, log): - self.log = log - - def pretty_string(self): + def hex_string(self): ret = self.__hex__() if ret[0] == "-": ret = ret[3:] else: ret = ret[2:] - ret += ": (" + str(self.host) + str(self.service) + str(self.job) + ")" + while len(ret) < 8: + ret = "0" + ret return ret + def set_logger(self, log): + self.log = log + + def pretty_string(self): + return self.hex_string() + ": (" + str(self.host) + str(self.service) + str(self.job) + ")" + def set_job(self, job): self.job = job From 131ce1a75be6dd93f84f48bb25e28a29073c3c33 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 10 Oct 2013 23:16:36 +0200 Subject: [PATCH 251/268] added hostgroup to Job --- bin/linspector | 2 +- linspector/core/job.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/linspector b/bin/linspector index 38359bb..cc287a8 100755 --- a/bin/linspector +++ b/bin/linspector @@ -114,7 +114,7 @@ def main(): for service in hostgroup.get_services(): for host in hostgroup.get_hosts(): for period in service.get_periods(): - job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core) + job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core, hostgroup) schedulerJob = period.createJob(scheduler, job, handleJob) if schedulerJob is not None: job.set_job(schedulerJob) diff --git a/linspector/core/job.py b/linspector/core/job.py index fc49733..a82f5be 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -32,21 +32,21 @@ def generateId(): class Job: - def __init__(self, service, host, members, processors, core): + def __init__(self, service, host, members, processors, core, hostgroup): self.service = service self.host = host self.members = members self.processors = processors self.core = core + self.hostgroup = hostgroup self.jobInfos = [] self.jobThreshold = 0 def __str__(self): return str(self.__dict__) - def __hex__(self): - return hex(crc32(str(self.service) + str(self.host) + str(self.members))) + return hex(crc32(str(self.hostgroup) + str(self.host) + str(self.service) + str(self.members))) def hex_string(self): ret = self.__hex__() @@ -62,7 +62,9 @@ class Job: self.log = log def pretty_string(self): - return self.hex_string() + ": (" + str(self.host) + str(self.service) + str(self.job) + ")" + ret = (self.hex_string() + ": (Hostgroup: " + str(self.hostgroup.get_name()) + + " Host: " + str(self.host) + " Service: " + str(self.service) + str(self.job) + ")") + return ret def set_job(self, job): self.job = job @@ -103,7 +105,7 @@ class Job: class JobInfo(object): - def __init__(self,jobHex, host, service): + def __init__(self, jobHex, host, service): self.id = generateId() self.jobHex = jobHex self.host = host From 0767965fb595230d2c2f8896a16c3ed14fb068a3 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 10 Oct 2013 23:19:24 +0200 Subject: [PATCH 252/268] added hex_string to JobInfo instead of the raw hex --- linspector/core/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector/core/job.py b/linspector/core/job.py index a82f5be..87b813f 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -90,7 +90,7 @@ class Job: self.log.debug("handle call") self.log.debug(self.service) try: - jobInfo = JobInfo(self.__hex__(), self.host, self.service) + jobInfo = JobInfo(self.hex_string(), self.host, self.service) self.service._execute(jobInfo) jobInfo.set_execution_end() From 90d8e81775e00070b69bfc1976a9265c0f06a633 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 10 Oct 2013 23:43:40 +0200 Subject: [PATCH 253/268] typo fix --- linspector/core/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linspector/core/job.py b/linspector/core/job.py index 87b813f..9f9d45b 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -63,7 +63,7 @@ class Job: def pretty_string(self): ret = (self.hex_string() + ": (Hostgroup: " + str(self.hostgroup.get_name()) + - " Host: " + str(self.host) + " Service: " + str(self.service) + str(self.job) + ")") + " Host: " + str(self.host) + " Service: " + str(self.service) + " " + str(self.job) + ")") return ret def set_job(self, job): From 1e04d58e5a7647a301d682d8e4c604c6dcf92d33 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 10 Oct 2013 23:44:20 +0200 Subject: [PATCH 254/268] new msg output with hex id --- linspector/services/tcpconnect.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linspector/services/tcpconnect.py b/linspector/services/tcpconnect.py index 2bfcf70..29744bb 100644 --- a/linspector/services/tcpconnect.py +++ b/linspector/services/tcpconnect.py @@ -44,21 +44,21 @@ class TcpconnectService(Service): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, msg: jobInfo.set_errorcode(2) - jobInfo.set_message("[tcpconnect: " + jobInfo.jobHex + "] Could not create socket to host: " + jobInfo.get_host() + - " on port: " + str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("[tcpconnect: " + jobInfo.jobHex + "] Could not create socket to host: " + + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") try: sock.connect((jobInfo.get_host(), self.port)) except socket.error, msg: jobInfo.set_errorcode(1) - jobInfo.set_message("[tcpconnect] Could not establish connection to host: " + jobInfo.get_host() + - " on port: " + str(self.port) + " (" + str(msg) + ")") + jobInfo.set_message("[tcpconnect: " + jobInfo.jobHex + "] Could not establish connection to host: " + + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") if jobInfo.get_errorcode() == -1: jobInfo.set_execution_successful(True) jobInfo.set_errorcode(0) - jobInfo.set_message("[tcpconnect] Connection successful established to host: " + jobInfo.get_host() + - " on port: " + str(self.port)) + jobInfo.set_message("[tcpconnect: " + jobInfo.jobHex + "] Connection successful established to host: " + + jobInfo.get_host() + " on port: " + str(self.port)) sock.close() From e12e05dbc78326be78fa84a61990e972ad706b02 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 00:03:18 +0200 Subject: [PATCH 255/268] added job enable/disble stuff --- linspector/core/job.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/linspector/core/job.py b/linspector/core/job.py index 9f9d45b..d0fa1a5 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -41,6 +41,7 @@ class Job: self.hostgroup = hostgroup self.jobInfos = [] self.jobThreshold = 0 + self._enabled = True def __str__(self): return str(self.__dict__) @@ -89,19 +90,26 @@ class Job: def handle_call(self): self.log.debug("handle call") self.log.debug(self.service) - try: - jobInfo = JobInfo(self.hex_string(), self.host, self.service) - self.service._execute(jobInfo) - jobInfo.set_execution_end() + if self._enabled: + try: + jobInfo = JobInfo(self.hex_string(), self.host, self.service) + self.service._execute(jobInfo) + jobInfo.set_execution_end() - self.handle_threshold(jobInfo, self.service.get_threshold(), jobInfo.was_execution_successful()) + self.handle_threshold(jobInfo, self.service.get_threshold(), jobInfo.was_execution_successful()) - self.log.debug("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) + self.log.debug("Code: " + str(jobInfo.get_errorcode()) + ", Message: " + str(jobInfo.get_message())) - self.jobInfos.append(jobInfo) + self.jobInfos.append(jobInfo) - except Exception, e: - self.log.debug(e) + except Exception, e: + self.log.debug(e) + + def enable(self): + self._enabled = True + + def disable(self): + self._enabled = False class JobInfo(object): From 494454c4e78b3ccad14ca0640ee4a31a262db2d5 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 00:05:40 +0200 Subject: [PATCH 256/268] a lot of new stuff in lish --- linspector/frontends/lish.py | 60 +++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/linspector/frontends/lish.py b/linspector/frontends/lish.py index ffc89af..ee425c0 100644 --- a/linspector/frontends/lish.py +++ b/linspector/frontends/lish.py @@ -1,7 +1,8 @@ """ -Lish is the Linspector Interactive Shell... +Lish is the Linspector Interactive Shell. -This will become a commandline interface to Linspector. Think of a network switch or router like those from Cisco. +This will become a commandline interface to Linspector. Think of a +network switch or router like those from Cisco. Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" @@ -21,13 +22,12 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ - from linspector.frontends.frontend import Frontend import os from shlex import split as shsplit from cmd import Cmd -__version__ = "0.1" +__version__ = "0.1.1" class LishFrontend(Frontend): @@ -128,7 +128,6 @@ class HostgroupCommander(Exit, object): class LishCommander(Exit, ShellCommander, LogCommander): - def __init__(self, kwargs): super(LishCommander, self).__init__() @@ -167,31 +166,44 @@ class LishCommander(Exit, ShellCommander, LogCommander): except KeyboardInterrupt, key: pass + def complete_hostgroup(self, text, line, begidx, endidx): + if begidx == 10: + return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs + + def help_hostgroup(self): + print "usage:\n\t" + \ + "hostgroup list\n\t\t\t" + \ + "prints a list of all hostgroups\n\t" + \ + "hostgroup select HOSTGROUPNAME\n\t\t\t" + \ + "select a hostgroup to make changes on it" + def do_python(self, text): exec text + def help_python(self): + print "executes python using 'exec'." + + def do_job(self, text): + if text == "disable": + pass + elif text == "enable": + pass + else: + print "invalid or missing parameter\n" + self.help_job() + + def help_job(self): + print "Job helper functions:\n\t" + \ + "disable :\t\tdisable a job\n\t" + \ + "enable :\t\tenable a job\n\t" + def do_jobs(self, text): if text == "list": for job in self._jobs: print job.pretty_string() + else: + print "invalid or missing parameter\n" + self.help_jobs() def help_jobs(self): - print "Job helper functions" - - def help_python(self): - print ''' - executes python using 'exec'. - ''' - - def help_hostgroup(self): - print ''' - usage: - hostgroup list - prints a list of all hostgroups - hostgroup select HOSTGROUPNAME - select a hostgroup to make changes on it - ''' - - def complete_hostgroup(self, text, line, begidx, endidx): - if begidx == 10: - return [x for x in self._hostgroupArgs if x.startswith(text)] if len(text) > 0 else self._hostgroupArgs \ No newline at end of file + print "Joblist helper functions:\n\t" + "list:\t\t\tlists all jobs" \ No newline at end of file From 0cb05861b0cfd3a97a75ebc9cc9288c29f9ded49 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 00:19:53 +0200 Subject: [PATCH 257/268] added some more logging --- linspector/core/job.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linspector/core/job.py b/linspector/core/job.py index d0fa1a5..63f2632 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -104,6 +104,8 @@ class Job: except Exception, e: self.log.debug(e) + else: + self.log.debug("Job " + self.hex_string() + " disabled") def enable(self): self._enabled = True From 7886e6f677e66fec440b2c845ab66f00913151ca Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 00:59:43 +0200 Subject: [PATCH 258/268] just enabled debug level logging... --- bin/linspector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/linspector b/bin/linspector index cc287a8..474a94a 100755 --- a/bin/linspector +++ b/bin/linspector @@ -67,9 +67,9 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfile if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) - logging.basicConfig(level=logging.WARNING) + #logging.basicConfig(level=logging.WARNING) log = logging.getLogger(__name__) - #log.setLevel(logging.ERROR) + log.setLevel(logging.DEBUG) consoleHandler = logging.StreamHandler() consoleHandler.setLevel(logLevel) From ee5245eccbe9015633a542a802ee2d1ea5808914 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:07:55 +0200 Subject: [PATCH 259/268] added threshold handling to job.py and config --- examples/linspector.json | 2 ++ linspector/core/job.py | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/examples/linspector.json b/examples/linspector.json index 790cdcb..c6e3c07 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -184,10 +184,12 @@ } }, "core":{ + "_documentation": "https://github.com/linspector/linspector/wiki/Configuration-Core", "instance_name": "Master Monitoring (monitor.example.org)", "max_logfile_size": 1024000, "max_logfile_count": 4, "max_worker_threads": 8, + "threshold_handling": "reset", "members":[ "root" ], "backends": { "jsonrpc": { diff --git a/linspector/core/job.py b/linspector/core/job.py index 63f2632..d88bbd0 100644 --- a/linspector/core/job.py +++ b/linspector/core/job.py @@ -73,7 +73,15 @@ class Job: def handle_threshold(self, jobInfo, serviceThreshold, executionSucessful): if executionSucessful: if self.jobThreshold > 0: - self.jobThreshold -= 1 + #TODO: maybe set threshold_handling for each service optionally; will override core setting! + if self.core["threshold_handling"] == "reset": + # Reset counter to 0 + self.log.debug("Threshold Reset") + self.jobThreshold = 0 + else: + # Decrement the counter (default) + self.log.debug("Threshold Decrement") + self.jobThreshold -= 1 else: self.jobThreshold += 1 From 1de3fd29e2c93cef1ca3f60ed0ad91776fc6bac9 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:20:23 +0200 Subject: [PATCH 260/268] version bump to 0.7 --- bin/linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/linspector b/bin/linspector index 474a94a..fc0908d 100755 --- a/bin/linspector +++ b/bin/linspector @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -__version__ = "0.6/TCPCONNECT" +__version__ = "0.7" __default_config__ = "./examples/minimal.json" import argparse From 5ecee5b0697aacdd282d458a87319a9c4847d033 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:29:25 +0200 Subject: [PATCH 261/268] some doc fixes in header --- linspector/services/tcpconnect.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linspector/services/tcpconnect.py b/linspector/services/tcpconnect.py index 29744bb..af0cd40 100644 --- a/linspector/services/tcpconnect.py +++ b/linspector/services/tcpconnect.py @@ -1,8 +1,8 @@ """ -The tcpconnect service. This is to check if a service on a specific port is reachable. +The tcpconnect service. This is to check if a TCP service on a specific +port is reachable. -This should just return 0 on success and NOT 0 on error. Just to make internals generic to just report this code and -not use a parser. +This should just return 0 on success and NOT 0 on error. Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" From e6741b0db9b8ce9dd076b797012b517ffcfa5416 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:30:22 +0200 Subject: [PATCH 262/268] added udpconnect service. should be tested! think it is not working like it is... ;) --- linspector/services/udpconnect.py | 67 +++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 linspector/services/udpconnect.py diff --git a/linspector/services/udpconnect.py b/linspector/services/udpconnect.py new file mode 100644 index 0000000..0f35335 --- /dev/null +++ b/linspector/services/udpconnect.py @@ -0,0 +1,67 @@ +""" +The udpconnect service. This is to check if a UDP service on a specific +port is reachable. + +This should just return 0 on success and NOT 0 on error. + +Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" + +This file is part of Linspector (http://linspector.org). + +Linspector is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +""" + +import socket +from linspector.services.service import Service + + +class UdpconnectService(Service): + def __init__(self, **kwargs): + super(UdpconnectService, self).__init__(**kwargs) + + args = self.get_arguments() + if "port" in args: + self.port = args["port"] + else: + raise Exception("There is no port set") + + def needs_arguments(self): + return True + + def execute(self, jobInfo): + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + except socket.error, msg: + jobInfo.set_errorcode(2) + jobInfo.set_message("[udpconnect: " + jobInfo.jobHex + "] Could not create socket to host: " + + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") + + try: + sock.connect((jobInfo.get_host(), self.port)) + except socket.error, msg: + jobInfo.set_errorcode(1) + jobInfo.set_message("[udpconnect: " + jobInfo.jobHex + "] Could not establish connection to host: " + + jobInfo.get_host() + " on port: " + str(self.port) + " (" + str(msg) + ")") + + if jobInfo.get_errorcode() == -1: + jobInfo.set_execution_successful(True) + jobInfo.set_errorcode(0) + jobInfo.set_message("[udpconnect: " + jobInfo.jobHex + "] Connection successful established to host: " + + jobInfo.get_host() + " on port: " + str(self.port)) + + sock.close() + + +def create(kwargs): + return UdpconnectService(**kwargs) \ No newline at end of file From 68f8cbadc9a6be12d5fdd6933fc6b85851f7d2f8 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:43:14 +0200 Subject: [PATCH 263/268] shutting logging down after the scheduler... makes sense i think --- bin/linspector | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/linspector b/bin/linspector index fc0908d..edeb8d3 100755 --- a/bin/linspector +++ b/bin/linspector @@ -131,8 +131,8 @@ def main(): frontend = LishFrontend(jobs=jobs, scheduler=scheduler, linspectorConfig=linConf) log.debug("shutting down scheduler") - logging.shutdown() scheduler.shutdown(wait=True) + logging.shutdown() if __name__ == "__main__": From dd1c6958c3197da12cbb752a2d07609696c6f590 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 02:48:27 +0200 Subject: [PATCH 264/268] some housekeeping --- bin/linspector | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bin/linspector b/bin/linspector index edeb8d3..58911cd 100755 --- a/bin/linspector +++ b/bin/linspector @@ -35,7 +35,7 @@ from linspector.backends.https import HttpsBackend from linspector.frontends.lish import LishFrontend -def parseArgs(): +def parse_args(): parser = argparse.ArgumentParser( description="Linspector is for monitoring the vital information of hosts, services and devices in a network.", epilog="linspector is not some program expecting computers to run! Visit http://linspector.org for more " @@ -62,7 +62,7 @@ def parseArgs(): return parser.parse_args() -def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfileLevel=logging.DEBUG): +def setup_logging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfileLevel=logging.DEBUG): logfile = path.expanduser(logfile) if not path.exists(path.dirname(logfile)): os.makedirs(path.dirname(logfile)) @@ -90,14 +90,14 @@ def setupLogging(logfile="./log/linspector.log", logLevel=logging.ERROR, logfile return log -def handleJob(jobInfo): +def handle_job(jobInfo): jobInfo.handle_call() def main(): - args = parseArgs() + args = parse_args() #TODO: catch all log messages (apscheduler etc.); make logging more generic to support libraries logging - log = setupLogging(args.logfile, args.loglevel) + log = setup_logging(args.logfile, args.loglevel) log.info("parsed arguments") @@ -115,7 +115,7 @@ def main(): for host in hostgroup.get_hosts(): for period in service.get_periods(): job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core, hostgroup) - schedulerJob = period.createJob(scheduler, job, handleJob) + schedulerJob = period.createJob(scheduler, job, handle_job) if schedulerJob is not None: job.set_job(schedulerJob) job.set_logger(log) From 252275559569ae91308801022ce14367c57f3cad Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Fri, 11 Oct 2013 04:22:32 +0200 Subject: [PATCH 265/268] yeah --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 651d0e2..114fa0b 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,11 @@ nbproject distfiles docs +documentation files local log plugins .metadata -examples/private.json \ No newline at end of file +examples/private.json From f3aa26cc1597a86e6d41baa3ea8a068b5c4b0834 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sat, 12 Oct 2013 02:31:41 +0200 Subject: [PATCH 266/268] just some new ideas --- examples/linspector.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/linspector.json b/examples/linspector.json index c6e3c07..90980c1 100644 --- a/examples/linspector.json +++ b/examples/linspector.json @@ -170,6 +170,7 @@ } }, "layouts":{ + "_comment": "https://github.com/linspector/linspector/wiki/Configuration-Layouts", "production":{ "hostgroups":[ "group1" ], "enabled": true @@ -184,7 +185,7 @@ } }, "core":{ - "_documentation": "https://github.com/linspector/linspector/wiki/Configuration-Core", + "_comment": "https://github.com/linspector/linspector/wiki/Configuration-Core", "instance_name": "Master Monitoring (monitor.example.org)", "max_logfile_size": 1024000, "max_logfile_count": 4, @@ -193,6 +194,7 @@ "members":[ "root" ], "backends": { "jsonrpc": { + "_comment": "https://github.com/linspector/linspector/wiki/Configuration-Core-Backends-JsonRPC", "host": "127.0.0.1", "port": "2323", "username": "linspector", From e524bf3797f2378199682032e2c8172eac160061 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Sat, 12 Oct 2013 02:34:39 +0200 Subject: [PATCH 267/268] deleted the abstracted daemon and moved class over to daemon.py --- linspector/core/daemon.py | 21 ++++++++++++++ linspector/core/linspector_daemon.py | 42 ---------------------------- 2 files changed, 21 insertions(+), 42 deletions(-) delete mode 100644 linspector/core/linspector_daemon.py diff --git a/linspector/core/daemon.py b/linspector/core/daemon.py index c80bb2d..799b48f 100644 --- a/linspector/core/daemon.py +++ b/linspector/core/daemon.py @@ -24,6 +24,27 @@ import time import atexit from signal import SIGTERM +""" +TODO: Think about, that daemonizing this software is not our goal but when we want to that, this needs a rewrite and +should maybe move over to the daemon frontend. daemon.py will remain the the base for this and should stay in linspector/core . +Since a daemon it normally not a frontend we should think about how to handle this. When daemonizing a real frontend +like "Lish" will make no sense but a frontend like "https" or "xmpp" could be useful anyway... +""" + + +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) + class Daemon: """ diff --git a/linspector/core/linspector_daemon.py b/linspector/core/linspector_daemon.py deleted file mode 100644 index ee9d940..0000000 --- a/linspector/core/linspector_daemon.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Copyright (c) 2011-2013 "Johannes Findeisen and Rafael Timmerberg" - -This file is part of Linspector (http://linspector.org). - -Linspector is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -This program 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . -""" - -from ..core import logger -from ..core.daemon import Daemon - -""" -TODO: Think about, that daemonizing this software is not our goal but when we want to that, this needs a rewrite and -should maybe move over to the daemon frontend. daemon.py will remain the the base for this and should stay in linspector/core . -Since a daemon it normally not a frontend we should think about how to handle this. When daemonizing a real frontend -like "Lish" will make no sense but a frontend like "https" or "xmpp" could be useful anyway... -""" - - -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) \ No newline at end of file From c08b5a1b13c562666c0b092ceb9e3fd59072edb7 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Thu, 17 Oct 2013 08:20:11 +0200 Subject: [PATCH 268/268] changed version from 0.7 to 0.1.7; we are really just 0.1.* currently --- bin/linspector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/linspector b/bin/linspector index 58911cd..17cb128 100755 --- a/bin/linspector +++ b/bin/linspector @@ -19,7 +19,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . """ -__version__ = "0.7" +__version__ = "0.1.7" __default_config__ = "./examples/minimal.json" import argparse @@ -136,4 +136,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main()