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
diff --git a/bin/linspector b/bin/linspector
index 38359bb..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.6/TCPCONNECT"
+__version__ = "0.1.7"
__default_config__ = "./examples/minimal.json"
import argparse
@@ -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,14 +62,14 @@ 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))
- 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)
@@ -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")
@@ -114,8 +114,8 @@ 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)
- schedulerJob = period.createJob(scheduler, job, handleJob)
+ job = Job(service, host, hostgroup.get_members(), hostgroup.get_processors(), core, hostgroup)
+ schedulerJob = period.createJob(scheduler, job, handle_job)
if schedulerJob is not None:
job.set_job(schedulerJob)
job.set_logger(log)
@@ -131,9 +131,9 @@ 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__":
- main()
\ No newline at end of file
+ main()
diff --git a/examples/linspector.json b/examples/linspector.json
index 790cdcb..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,13 +185,16 @@
}
},
"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,
"max_worker_threads": 8,
+ "threshold_handling": "reset",
"members":[ "root" ],
"backends": {
"jsonrpc": {
+ "_comment": "https://github.com/linspector/linspector/wiki/Configuration-Core-Backends-JsonRPC",
"host": "127.0.0.1",
"port": "2323",
"username": "linspector",
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/job.py b/linspector/core/job.py
index fc49733..d88bbd0 100644
--- a/linspector/core/job.py
+++ b/linspector/core/job.py
@@ -32,21 +32,22 @@ 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
+ self._enabled = True
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 +63,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
@@ -70,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
@@ -87,23 +98,32 @@ class Job:
def handle_call(self):
self.log.debug("handle call")
self.log.debug(self.service)
- try:
- jobInfo = JobInfo(self.__hex__(), 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)
+ else:
+ self.log.debug("Job " + self.hex_string() + " disabled")
+
+ def enable(self):
+ self._enabled = True
+
+ def disable(self):
+ self._enabled = False
class JobInfo(object):
- def __init__(self,jobHex, host, service):
+ def __init__(self, jobHex, host, service):
self.id = generateId()
self.jobHex = jobHex
self.host = host
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
diff --git a/linspector/services/tcpconnect.py b/linspector/services/tcpconnect.py
index 2bfcf70..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"
@@ -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()
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