Automatic code cleanups and import optimizations.

This commit is contained in:
Johannes Findeisen 2023-02-12 03:31:52 +01:00
commit b308068617
26 changed files with 6738 additions and 5928 deletions

123
README.md
View file

@ -4,13 +4,13 @@
## About ## About
The idea is based on a software I developed around 2010 or so. The name of the software was The idea is based on a software I developed around 2010 or so. The name of the software was
[Linspector](https://linspector.org/) but the implementation was just too [Linspector](https://linspector.org/) but the implementation was just too
complicated. The idea still remains so here is the rebirth of Linspector. First commits complicated. The idea still remains so here is the rebirth of Linspector. First commits
of this rewrite where done as a new project named of this rewrite where done as a new project named
[monipy](https://git.unixpeople.org/linspector/monipy), but I moved to the name [monipy](https://git.unixpeople.org/linspector/monipy), but I moved to the name
Linspector because I believe it is the better and cooler name... Old Linspector code is Linspector because I believe it is the better and cooler name... Old Linspector code is
not available in this repository anymore, you can find it under not available in this repository anymore, you can find it under
[https://git.unixpeople.org/linspector/linspector-old](https://git.unixpeople.org/linspector/linspector-old). [https://git.unixpeople.org/linspector/linspector-old](https://git.unixpeople.org/linspector/linspector-old).
Hope this project will become useful for someone at some day and not only for Hope this project will become useful for someone at some day and not only for
@ -28,80 +28,80 @@ I design the software actually and try to convert my ideas to software.
### Environment ### Environment
My development environment is running using a virtual Python environment. I am using My development environment is running using a virtual Python environment. I am using
all packages defined in requirements.txt. all packages defined in requirements.txt.
Linspector includes a Makefile for executing bin/linspector without writing the full Linspector includes a Makefile for executing bin/linspector without writing the full
command with pretended PYTHONPATH. This makes my work a little easier. command with pretended PYTHONPATH. This makes my work a little easier.
The IDE I am using is [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/) The IDE I am using is [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/)
with Python plugin and / or [PyCharm Community](https://www.jetbrains.com/pycharm/) from with Python plugin and / or [PyCharm Community](https://www.jetbrains.com/pycharm/) from
[JetBrains](https://www.jetbrains.com/). I mention the IDE here because I am very thankful [JetBrains](https://www.jetbrains.com/). I mention the IDE here because I am very thankful
to JetBrains for providing such a nice piece of software. I have never seen such a perfect to JetBrains for providing such a nice piece of software. I have never seen such a perfect
development environment. development environment.
### To do ### To do
- **Everything!** But the progress is fast and after some few days I am not far - **Everything!** But the progress is fast and after some few days I am not far
away to get a first working codebase. If the core is running I believe adding features away to get a first working codebase. If the core is running I believe adding features
will happen from day to day... ;) will happen from day to day... ;)
See TODO for internal tasks. See TODO for internal tasks.
### Ideas ### Ideas
- **Thousands!** For now the goal is to implement most features from the old version - **Thousands!** For now the goal is to implement most features from the old version
of Linspector. :) of Linspector. :)
### Manifest ### Manifest
- All of this project **must be MIT licensed**. When using 3rd party libraries make - All of this project **must be MIT licensed**. When using 3rd party libraries make
sure the license is compatible but MIT should always be preferred if an sure the license is compatible but MIT should always be preferred if an
alternative is available. alternative is available.
- The core of Linspector should not use 3rd party libraries. Only plugins, - The core of Linspector should not use 3rd party libraries. Only plugins,
notifications and types may use other libraries. But copying code into the notifications and types may use other libraries. But copying code into the
source tree is ok when respecting the license. Not using 3rd party libraries source tree is ok when respecting the license. Not using 3rd party libraries
should always be preferred though. should always be preferred though.
- Inline comments should be all lowercase. Descriptions and documentation comments - Inline comments should be all lowercase. Descriptions and documentation comments
must be natural language. must be natural language.
- Arguments to functions must always be in alphabetical order. - Arguments to functions must always be in alphabetical order.
- Class member variables must always be in alphabetical order in __init__() or any - Class member variables must always be in alphabetical order in __init__() or any
function / method. function / method.
- Every commit must run without errors even if not being a working version of Linspector. - Every commit must run without errors even if not being a working version of Linspector.
### Required libraries ### Required libraries
Currently, the Linspector core requires the following 3rd party libraries: Currently, the Linspector core requires the following 3rd party libraries:
- [APScheduler](https://github.com/agronholm/apscheduler) - This is the scheduler in - [APScheduler](https://github.com/agronholm/apscheduler) - This is the scheduler in
Linspector for execution of monitors. I started Linspector for execution of monitors. I started
to use this library in very early versions of Linspector in 2011. Since the main task to use this library in very early versions of Linspector in 2011. Since the main task
in Linspector is the execution of jobs in regularly intervals I believe it is the right in Linspector is the execution of jobs in regularly intervals I believe it is the right
decision to make use of APScheduler directly in the core of the Linspector project. decision to make use of APScheduler directly in the core of the Linspector project.
### Other used libraries ### Other used libraries
monitors, notifications, services or plugins sometimes need to make the use of monitors, notifications, services or plugins sometimes need to make the use of
3rd party libraries, but they are not required to run Linspector properly. Not installing 3rd party libraries, but they are not required to run Linspector properly. Not installing
them may only affect parts of Linspector. Currently used libraries are: them may only affect parts of Linspector. Currently used libraries are:
- [CherryPy](https://cherrypy.dev/) - CherryPy is a pythonic, object-oriented HTTP framework. - [CherryPy](https://cherrypy.dev/) - CherryPy is a pythonic, object-oriented HTTP framework.
Used by the HTTPServer plugin. Used by the HTTPServer plugin.
- [fritzconnection](https://github.com/kbr/fritzconnection) - A Python-Tool to communicate with - [fritzconnection](https://github.com/kbr/fritzconnection) - A Python-Tool to communicate with
the AVM Fritz!Box. Uses the TR-064 protocol over UPnP. Used by the FritzboxPhoneStatus and the AVM Fritz!Box. Uses the TR-064 protocol over UPnP. Used by the FritzboxPhoneStatus and
FritzBoxUplink service. FritzBoxUplink service.
- [Paramiko](https://www.paramiko.org/) - Paramiko is a pure-Python (2.7, 3.4+) implementation - [Paramiko](https://www.paramiko.org/) - Paramiko is a pure-Python (2.7, 3.4+) implementation
of the SSHv2 protocol, providing both client and server functionality. Used by the SSH service. of the SSHv2 protocol, providing both client and server functionality. Used by the SSH service.
- [python-gammu](https://wammu.eu/python-gammu/) - Python bindings for the Gammu library. Used by the - [python-gammu](https://wammu.eu/python-gammu/) - Python bindings for the Gammu library. Used by the
SMS notification. SMS notification.
- [PySNMP](https://pysnmp.readthedocs.io/en/latest/) - PySNMP is a cross-platform, pure-Python - [PySNMP](https://pysnmp.readthedocs.io/en/latest/) - PySNMP is a cross-platform, pure-Python
SNMP engine implementation. It features fully-functional SNMP engine capable to act in SNMP engine implementation. It features fully-functional SNMP engine capable to act in
Agent/Manager/Proxy roles, talking SNMP v1/v2c/v3 protocol versions over IPv4/IPv6 and other Agent/Manager/Proxy roles, talking SNMP v1/v2c/v3 protocol versions over IPv4/IPv6 and other
network transports. Used by the SNMP services (get). network transports. Used by the SNMP services (get).
- [requests](https://requests.readthedocs.io/en/latest/) - Requests is an elegant and simple - [requests](https://requests.readthedocs.io/en/latest/) - Requests is an elegant and simple
HTTP library for Python, built for human beings. Used by the Speedtest service. HTTP library for Python, built for human beings. Used by the Speedtest service.
- [xmpp2](https://pypi.org/project/xmpp2/) - A XMPP client for Python. Used by the XMPP notification. - [xmpp2](https://pypi.org/project/xmpp2/) - A XMPP client for Python. Used by the XMPP notification.
These libraries are not being delivered with the Linspector source code and maybe have These libraries are not being delivered with the Linspector source code and maybe have
different and incompatible licenses. You need to install them using pip, your OS package different and incompatible licenses. You need to install them using pip, your OS package
manager or any other possible way. manager or any other possible way.
@ -112,9 +112,9 @@ scheme (See: [https://semver.org/](https://semver.org/)):
#### MAJOR.MINOR.MAINTENANCE #### MAJOR.MINOR.MAINTENANCE
- **MAJOR** changes _can_ change the API. The lesser, the better. It _expects_ a - **MAJOR** changes _can_ change the API. The lesser, the better. It _expects_ a
complete documentation. complete documentation.
- **MINOR** changes _must_ not break the API. New features are placed here. - **MINOR** changes _must_ not break the API. New features are placed here.
- **MAINTENANCE** changes are "just-in-time" changes or small enhancements which _should_ - **MAINTENANCE** changes are "just-in-time" changes or small enhancements which _should_
not affect the documentation and _must_ not break the API. not affect the documentation and _must_ not break the API.
@ -129,15 +129,16 @@ complete documentation.
- 15.10 - Date based release - 15.10 - Date based release
- 23 - Serial release - 23 - Serial release
(More information: [https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#choosing-a-versioning-scheme](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#choosing-a-versioning-scheme) & (More
information: [https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#choosing-a-versioning-scheme](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#choosing-a-versioning-scheme) &
[https://peps.python.org/pep-0440/#public-version-identifiers](https://peps.python.org/pep-0440/#public-version-identifiers)) [https://peps.python.org/pep-0440/#public-version-identifiers](https://peps.python.org/pep-0440/#public-version-identifiers))
### Configuration file rules ### Configuration file rules
- No inline comments so every available character can be used in values - No inline comments so every available character can be used in values
- Values can be overridden in each monitor - Values can be overridden in each monitor
- File names in etc/* are not important but section names and key names. - File names in etc/* are not important but section names and key names.
- Comments can be inserted using ';' or '#' - Comments can be inserted using ';' or '#'
## FAQ ## FAQ
@ -149,27 +150,27 @@ monitoring a small amount of services for some years.
### Should I try the old version of Linspector? ### Should I try the old version of Linspector?
I recommend not to use the old version of Linspector because the new version will I recommend not to use the old version of Linspector because the new version will
in no way become backward compatible. Features of the old version will nearly all be in no way become backward compatible. Features of the old version will nearly all be
implemented in the new version so if you can wait a little then I recommend to wait implemented in the new version so if you can wait a little then I recommend to wait
until I release the new version of Linspector. until I release the new version of Linspector.
### Can I use an old configuration of Linspector in the new version? ### Can I use an old configuration of Linspector in the new version?
No! The new configuration does not use JSON files anymore but an INI file syntax based on No! The new configuration does not use JSON files anymore but an INI file syntax based on
a directory tree. a directory tree.
### Why should I use Linspecter even there are other mature and stable tools available already? ### Why should I use Linspecter even there are other mature and stable tools available already?
Linpector aims to be very small and simple and even should work in home or small Linpector aims to be very small and simple and even should work in home or small
environments. But Linspector also is useful in very large infrastructures for monitoring environments. But Linspector also is useful in very large infrastructures for monitoring
thousands of devices and services. thousands of devices and services.
### Can I run multiple instances of the Linspector daemon? ### Can I run multiple instances of the Linspector daemon?
Yes, of course. Since you add a configuration path when running Linspector you can Yes, of course. Since you add a configuration path when running Linspector you can
just pass a different path to a configuration tree to each instance. And since you just pass a different path to a configuration tree to each instance. And since you
can configure the PID file in each configuration you can even can start, stop or can configure the PID file in each configuration you can even can start, stop or
restart each instance in a native way. restart each instance in a native way.
## License ## License

View file

@ -12,11 +12,10 @@ import sys
from linspector.core.configuration import Configuration from linspector.core.configuration import Configuration
from linspector.core.environment import Environment from linspector.core.environment import Environment
from linspector.core.logger import Log
from linspector.core.linspector import Linspector from linspector.core.linspector import Linspector
from linspector.core.logger import Log
from linspector.core.monitors import Monitors from linspector.core.monitors import Monitors
# i currently only increase the 3rd number because the goal is that 0.19.* will become the first # i currently only increase the 3rd number because the goal is that 0.19.* will become the first
# stable version. # stable version.
__version__ = '0.19.62.dev1' __version__ = '0.19.62.dev1'
@ -79,7 +78,7 @@ def main():
try: try:
linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler) linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler)
#linspector.print_debug() # linspector.print_debug()
except Exception as err: except Exception as err:
log.critical('[linspector] core initialization error: {0}'.format(err)) log.critical('[linspector] core initialization error: {0}'.format(err))
sys.exit(1) sys.exit(1)

View file

@ -14,9 +14,10 @@ import logging.handlers
import os import os
import sys import sys
from linspector.core.helpers import log
from linspector.core.configuration import Configuration from linspector.core.configuration import Configuration
from linspector.core.environment import Environment from linspector.core.environment import Environment
from linspector.core.helpers import log
from linspector.core.linspector import Linspector from linspector.core.linspector import Linspector
from linspector.core.monitors import Monitors from linspector.core.monitors import Monitors
@ -127,7 +128,7 @@ def main():
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
elif log_level == "debug": elif log_level == "debug":
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
#elif configuration.get_option('linspector', 'log_level') != 'error' != 'warning' \ # elif configuration.get_option('linspector', 'log_level') != 'error' != 'warning' \
# != 'info' != 'debug': # != 'info' != 'debug':
# logger.warning('[linspector] log level: "' + log_level + '" not found!') # logger.warning('[linspector] log level: "' + log_level + '" not found!')
@ -138,7 +139,7 @@ def main():
try: try:
linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler) linspector = Linspector(configuration, environment, log, monitors, plugins, scheduler)
#linspector.print_debug() # linspector.print_debug()
except Exception as err: except Exception as err:
log('critical', '[linspector] core initialization error: {0}'.format(err)) log('critical', '[linspector] core initialization error: {0}'.format(err))
sys.exit(1) sys.exit(1)

View file

@ -3,7 +3,7 @@
; report core errors to the following users ; report core errors to the following users
error_receivers = admin@example.com error_receivers = admin@example.com
; available log levels are: "error", "warning", "info" and "debug". if no log_level is set, it will be critical only. ; available log levels are: "error", "warning", "info" and "debug". if no log_level is set, it will be critical only.
log_level= debug log_level = debug
;log_file = ~/code/linspector/linspector/log/linspector.log ;log_file = ~/code/linspector/linspector/log/linspector.log
; number of log files to be kept. i recommend to use the lowest sensible value for keeping performance high. so set ; number of log files to be kept. i recommend to use the lowest sensible value for keeping performance high. so set
; the size of the log file higher to increase the log history. ; the size of the log file higher to increase the log history.

View file

@ -1,4 +1,4 @@
[httpserver] [httpserver]
ip = 127.0.0.1 ip = 127.0.0.1
port = 4242 port = 4242
type=thread type = thread

View file

@ -1,2 +1,2 @@
[lish] [lish]
type=none type = none

View file

@ -1,115 +1,158 @@
<?xml version="1.0" encoding="UTF-8"?><!-- Created with Inkscape (http://www.inkscape.org/) --><svg height="297mm" id="svg5088" inkscape:output_extension="org.inkscape.output.svg.inkscape" inkscape:version="0.46" sodipodi:version="0.32" width="210mm" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <?xml version="1.0" encoding="UTF-8"?><!-- Created with Inkscape (http://www.inkscape.org/) -->
<defs id="defs3"> <svg height="297mm" id="svg5088" inkscape:output_extension="org.inkscape.output.svg.inkscape" inkscape:version="0.46"
<inkscape:perspective id="perspective5094" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/> sodipodi:version="0.32" width="210mm" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#"
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3294" inkscape:collect="always" x1="606.10046" x2="470.78317" xlink:href="#linearGradient3288" y1="335.81693" y2="407.94183"/> xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3286" inkscape:collect="always" x1="22.627417" x2="342.23969" xlink:href="#linearGradient3280" y1="259.38269" y2="417.7746"/> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3276" inkscape:collect="always" x1="253.69392" x2="316.32159" xlink:href="#linearGradient3270" y1="392.06641" y2="276.10086"/> xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3266" inkscape:collect="always" x1="86.164584" x2="188.14864" xlink:href="#linearGradient3260" y1="169.8075" y2="169.8075"/> xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3228" inkscape:collect="always" x1="27.105211" x2="507.92923" xlink:href="#linearGradient3222" y1="261.07654" y2="405.32632"/> <defs id="defs3">
<linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3202" inkscape:collect="always" x1="222.18834" x2="464.36908" xlink:href="#linearGradient3196" y1="187.6158" y2="187.6158"/> <inkscape:perspective id="perspective5094" inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
<inkscape:perspective id="perspective3342" inkscape:persp3d-origin="372.04724 : 350.78739 : 1" inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0" inkscape:vp_z="744.09448 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/> inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0"
<linearGradient id="linearGradient3184"> inkscape:vp_z="744.09448 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
<stop id="stop3186" offset="0" style="stop-color:#c17d11;stop-opacity:1;"/> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3294" inkscape:collect="always" x1="606.10046"
<stop id="stop3192" offset="0.5" style="stop-color:#c17d11;stop-opacity:0.49803922;"/> x2="470.78317" xlink:href="#linearGradient3288" y1="335.81693" y2="407.94183"/>
<stop id="stop3194" offset="0.75" style="stop-color:#c17d11;stop-opacity:0.24705882;"/> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3286" inkscape:collect="always" x1="22.627417"
<stop id="stop3188" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/> x2="342.23969" xlink:href="#linearGradient3280" y1="259.38269" y2="417.7746"/>
</linearGradient> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3276" inkscape:collect="always" x1="253.69392"
<linearGradient id="linearGradient3196"> x2="316.32159" xlink:href="#linearGradient3270" y1="392.06641" y2="276.10086"/>
<stop id="stop3198" offset="0" style="stop-color:#c17d11;stop-opacity:1;"/> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3266" inkscape:collect="always" x1="86.164584"
<stop id="stop3204" offset="0.5" style="stop-color:#e9b96e;stop-opacity:1;"/> x2="188.14864" xlink:href="#linearGradient3260" y1="169.8075" y2="169.8075"/>
<stop id="stop3206" offset="0.75" style="stop-color:#e9b96e;stop-opacity:1;"/> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3228" inkscape:collect="always" x1="27.105211"
<stop id="stop3200" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/> x2="507.92923" xlink:href="#linearGradient3222" y1="261.07654" y2="405.32632"/>
</linearGradient> <linearGradient gradientUnits="userSpaceOnUse" id="linearGradient3202" inkscape:collect="always" x1="222.18834"
<linearGradient id="linearGradient3222"> x2="464.36908" xlink:href="#linearGradient3196" y1="187.6158" y2="187.6158"/>
<stop id="stop3224" offset="0" style="stop-color:#8f5902;stop-opacity:1;"/> <inkscape:perspective id="perspective3342" inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
<stop id="stop3230" offset="0.31874576" style="stop-color:#c17d11;stop-opacity:1;"/> inkscape:vp_x="0 : 526.18109 : 1" inkscape:vp_y="0 : 1000 : 0"
<stop id="stop3232" offset="0.65536499" style="stop-color:#e9b96e;stop-opacity:1;"/> inkscape:vp_z="744.09448 : 526.18109 : 1" sodipodi:type="inkscape:persp3d"/>
<stop id="stop3234" offset="0.76973599" style="stop-color:#e9b96e;stop-opacity:1;"/> <linearGradient id="linearGradient3184">
<stop id="stop3226" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/> <stop id="stop3186" offset="0" style="stop-color:#c17d11;stop-opacity:1;"/>
</linearGradient> <stop id="stop3192" offset="0.5" style="stop-color:#c17d11;stop-opacity:0.49803922;"/>
<linearGradient id="linearGradient3236"> <stop id="stop3194" offset="0.75" style="stop-color:#c17d11;stop-opacity:0.24705882;"/>
<stop id="stop3238" offset="0" style="stop-color:#ef9b96;stop-opacity:0.93725491;"/> <stop id="stop3188" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/>
<stop id="stop3240" offset="1" style="stop-color:#ffffff;stop-opacity:0;"/> </linearGradient>
</linearGradient> <linearGradient id="linearGradient3196">
<linearGradient id="linearGradient3260" inkscape:collect="always"> <stop id="stop3198" offset="0" style="stop-color:#c17d11;stop-opacity:1;"/>
<stop id="stop3262" offset="0" style="stop-color:#000000;stop-opacity:1;"/> <stop id="stop3204" offset="0.5" style="stop-color:#e9b96e;stop-opacity:1;"/>
<stop id="stop3264" offset="1" style="stop-color:#000000;stop-opacity:0;"/> <stop id="stop3206" offset="0.75" style="stop-color:#e9b96e;stop-opacity:1;"/>
</linearGradient> <stop id="stop3200" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/>
<linearGradient id="linearGradient3270"> </linearGradient>
<stop id="stop3272" offset="0" style="stop-color:#000000;stop-opacity:1;"/> <linearGradient id="linearGradient3222">
<stop id="stop3274" offset="1" style="stop-color:#000000;stop-opacity:0;"/> <stop id="stop3224" offset="0" style="stop-color:#8f5902;stop-opacity:1;"/>
</linearGradient> <stop id="stop3230" offset="0.31874576" style="stop-color:#c17d11;stop-opacity:1;"/>
<linearGradient id="linearGradient3280" inkscape:collect="always"> <stop id="stop3232" offset="0.65536499" style="stop-color:#e9b96e;stop-opacity:1;"/>
<stop id="stop3282" offset="0" style="stop-color:#000000;stop-opacity:1;"/> <stop id="stop3234" offset="0.76973599" style="stop-color:#e9b96e;stop-opacity:1;"/>
<stop id="stop3284" offset="1" style="stop-color:#000000;stop-opacity:0;"/> <stop id="stop3226" offset="1" style="stop-color:#c17d11;stop-opacity:1;"/>
</linearGradient> </linearGradient>
<linearGradient id="linearGradient3288" inkscape:collect="always"> <linearGradient id="linearGradient3236">
<stop id="stop3290" offset="0" style="stop-color:#8f5902;stop-opacity:1;"/> <stop id="stop3238" offset="0" style="stop-color:#ef9b96;stop-opacity:0.93725491;"/>
<stop id="stop3292" offset="1" style="stop-color:#8f5902;stop-opacity:0;"/> <stop id="stop3240" offset="1" style="stop-color:#ffffff;stop-opacity:0;"/>
</linearGradient> </linearGradient>
</defs> <linearGradient id="linearGradient3260" inkscape:collect="always">
<sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1" inkscape:cx="-285.71429" inkscape:cy="497.14286" inkscape:document-units="mm" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.35" pagecolor="#ffffff" showgrid="false"/> <stop id="stop3262" offset="0" style="stop-color:#000000;stop-opacity:1;"/>
<metadata id="metadata4"> <stop id="stop3264" offset="1" style="stop-color:#000000;stop-opacity:0;"/>
<rdf:RDF> </linearGradient>
<cc:Work rdf:about=""> <linearGradient id="linearGradient3270">
<dc:format>image/svg+xml</dc:format> <stop id="stop3272" offset="0" style="stop-color:#000000;stop-opacity:1;"/>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> <stop id="stop3274" offset="1" style="stop-color:#000000;stop-opacity:0;"/>
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/> </linearGradient>
<dc:title>inspector hat</dc:title> <linearGradient id="linearGradient3280" inkscape:collect="always">
<dc:date>Sept 2009</dc:date> <stop id="stop3282" offset="0" style="stop-color:#000000;stop-opacity:1;"/>
<dc:creator> <stop id="stop3284" offset="1" style="stop-color:#000000;stop-opacity:0;"/>
<cc:Agent> </linearGradient>
<dc:title>Franziska Sponsel</dc:title> <linearGradient id="linearGradient3288" inkscape:collect="always">
</cc:Agent> <stop id="stop3290" offset="0" style="stop-color:#8f5902;stop-opacity:1;"/>
</dc:creator> <stop id="stop3292" offset="1" style="stop-color:#8f5902;stop-opacity:0;"/>
<dc:rights> </linearGradient>
<cc:Agent> </defs>
<dc:title>Franziska Sponsel</dc:title> <sodipodi:namedview bordercolor="#666666" borderopacity="1.0" id="base" inkscape:current-layer="layer1"
</cc:Agent> inkscape:cx="-285.71429" inkscape:cy="497.14286" inkscape:document-units="mm"
</dc:rights> inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="0.35" pagecolor="#ffffff"
<dc:publisher> showgrid="false"/>
<cc:Agent> <metadata id="metadata4">
<dc:title>RRZE</dc:title> <rdf:RDF>
</cc:Agent> <cc:Work rdf:about="">
</dc:publisher> <dc:format>image/svg+xml</dc:format>
<dc:subject> <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<rdf:Bag> <cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/"/>
<rdf:li>inspector</rdf:li> <dc:title>inspector hat</dc:title>
<rdf:li>hat</rdf:li> <dc:date>Sept 2009</dc:date>
</rdf:Bag> <dc:creator>
</dc:subject> <cc:Agent>
<dc:contributor> <dc:title>Franziska Sponsel</dc:title>
<cc:Agent> </cc:Agent>
<dc:title>Beate Kaspar, Hendrik Eggers, Florian Löffler</dc:title> </dc:creator>
</cc:Agent> <dc:rights>
</dc:contributor> <cc:Agent>
</cc:Work> <dc:title>Franziska Sponsel</dc:title>
<cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/"> </cc:Agent>
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/> </dc:rights>
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/> <dc:publisher>
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/> <cc:Agent>
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/> <dc:title>RRZE</dc:title>
<cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/> </cc:Agent>
<cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/> </dc:publisher>
</cc:License> <dc:subject>
</rdf:RDF> <rdf:Bag>
</metadata> <rdf:li>inspector</rdf:li>
<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1"> <rdf:li>hat</rdf:li>
<g id="g6815"> </rdf:Bag>
<g id="g3296" transform="translate(57.978143,318.94882)"> </dc:subject>
<path d="M 85.298587,247.36749 C 85.298587,247.36749 47.634276,255.12191 32.125442,278.38516 C 16.616608,301.64841 4.4310954,320.48057 16.616608,339.31272 C 28.80212,358.14488 69.789753,395.80919 110.77739,399.13251 C 151.76502,402.45583 304.63781,445.65901 363.34982,437.90459 C 422.06184,430.15018 572.71908,402.45583 572.71908,402.45583 C 572.71908,402.45583 634.75442,384.73145 618.13781,350.39046 C 601.5212,316.04947 517.33039,289.4629 517.33039,289.4629" id="path3348" style="fill:url(#linearGradient3228);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> <dc:contributor>
<path d="M 80.867491,287.24735 C 80.867491,287.24735 93.053004,334.88163 122.9629,339.31272 C 152.87279,343.74382 305.74558,348.17491 326.79329,347.06714 C 347.84099,345.95936 494.06714,318.26502 510.68375,311.61837 C 527.30035,304.97173 515.11484,287.24735 515.11484,287.24735 C 515.11484,287.24735 479.66608,234.0742 477.45053,225.21201 C 475.23498,216.34982 460.83392,94.4947 458.61837,81.201413 C 456.40283,67.908127 436.4629,37.998233 402.12191,35.782686 C 367.78092,33.567138 281.37456,23.597173 263.65018,30.243816 C 245.9258,36.890459 149.54947,40.213781 130.71731,62.369258 C 111.88516,84.524735 80.867491,286.13958 80.867491,287.24735 z" id="path3346" style="fill:url(#linearGradient3202);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> <cc:Agent>
<path d="M 178.59568,55.443594 C 178.59568,55.443594 189.56209,66.409996 187.99546,88.342799 C 186.42883,110.2756 178.59568,284.1714 178.59568,284.1714 L 86.164584,276.33826 L 123.76368,64.843367 L 178.59568,55.443594 z" id="path4122" style="opacity:0.90119761;fill:url(#linearGradient3266);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/> <dc:title>Beate Kaspar, Hendrik Eggers, Florian Löffler</dc:title>
<path d="M 90.864471,274.77163 C 90.864471,274.77163 275.72667,296.70443 311.75913,292.00454 C 347.79159,287.30466 490.35482,260.67197 490.35482,260.67197 L 495.0547,257.53871 L 518.55413,298.27106 L 499.75459,315.50398 L 318.02565,348.40318 L 130.03019,339.00341 L 93.997728,320.20386 L 78.33144,290.43791 L 90.864471,274.77163 z" id="path4120" style="fill:#8f5902;fill-rule:evenodd;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> </cc:Agent>
<path d="M 531.08716,298.27106 L 610.98523,339.00341 L 623.51826,375.03587 L 576.5194,398.5353 L 459.02224,426.73462 C 459.02224,426.73462 476.25516,433.00114 510.72099,393.83542 C 545.18682,354.6697 534.22042,298.27106 531.08716,298.27106 z" id="path4124" style="fill:url(#linearGradient3294);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/> </dc:contributor>
<path d="M 73.631554,273.205 C 73.631554,273.205 48.565493,284.1714 48.565493,304.53757 C 48.565493,324.90375 45.432235,356.23632 61.098523,370.33598 C 76.764811,384.43564 130.03019,398.5353 130.03019,398.5353 C 130.03019,398.5353 89.297842,343.70329 89.297842,318.63723 C 89.297842,293.57117 73.631554,270.07174 73.631554,273.205 z" id="path4126" style="fill:#8f5902;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/> </cc:Work>
<path d="M 526,292 C 526,292 546,308 484,323 C 422,338 319,350 319,350 C 319,350 292,351 319,362 C 346,373 510,387 531,366 C 552,345 577,340 576,319 C 575,298 523,292 526,292 z" id="path3166" style="fill:#c17d11;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/> <cc:License rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
<path d="M 80.867491,287.24735 C 80.867491,287.24735 93.053004,334.88163 122.9629,339.31272 C 152.87279,343.74382 305.74558,348.17491 326.79329,347.06714 C 347.84099,345.95936 494.06714,318.26502 510.68375,311.61837 C 527.30035,304.97173 515.11484,287.24735 515.11484,287.24735 C 515.11484,287.24735 479.66608,234.0742 477.45053,225.21201 C 475.23498,216.34982 460.83392,94.4947 458.61837,81.201413 C 456.40283,67.908127 436.4629,37.998233 402.12191,35.782686 C 367.78092,33.567138 281.37456,23.597173 263.65018,30.243816 C 245.9258,36.890459 149.54947,40.213781 130.71731,62.369258 C 111.88516,84.524735 80.867491,286.13958 80.867491,287.24735 z" id="path2445" style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> <cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction"/>
<path d="M 85.298587,247.36749 C 85.298587,247.36749 47.634276,255.12191 32.125442,278.38516 C 16.616608,301.64841 4.4310954,320.48057 16.616608,339.31272 C 28.80212,358.14488 69.789753,395.80919 110.77739,399.13251 C 151.76502,402.45583 304.63781,445.65901 363.34982,437.90459 C 422.06184,430.15018 572.71908,402.45583 572.71908,402.45583 C 572.71908,402.45583 634.75442,384.73145 618.13781,350.39046 C 601.5212,316.04947 517.33039,289.4629 517.33039,289.4629" id="path3217" style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> <cc:permits rdf:resource="http://creativecommons.org/ns#Distribution"/>
<path d="M 90.864471,274.77163 C 90.864471,274.77163 275.72667,296.70443 311.75913,292.00454 C 347.79159,287.30466 490.35482,260.67197 490.35482,260.67197 L 495.0547,257.53871 L 518.55413,298.27106 L 499.75459,315.50398 L 318.02565,348.40318 L 130.03019,339.00341 L 93.997728,320.20386 L 78.33144,290.43791 L 90.864471,274.77163 z" id="path3268" style="opacity:0.71556869;fill:url(#linearGradient3276);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/> <cc:requires rdf:resource="http://creativecommons.org/ns#Notice"/>
<path d="M 77.781746,250.8974 L 79.195959,289.08117 L 110.30866,335.75022 L 175.36248,342.82128 L 298.39906,344.2355 L 470.93312,420.60303 L 332.34019,440.40202 L 142.83557,406.46089 L 35.355339,372.51977 L 5.6568542,320.19387 L 26.870058,282.0101 L 77.781746,250.8974 z" id="path3278" style="opacity:0.50898204;fill:url(#linearGradient3286);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/> <cc:requires rdf:resource="http://creativecommons.org/ns#Attribution"/>
</g> <cc:permits rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
<rect height="697.14288" id="rect5949" style="opacity:0.50898204000000002;fill:none;fill-opacity:1;stroke:none;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" width="697.14288" x="23.428572" y="183.79076"/> <cc:requires rdf:resource="http://creativecommons.org/ns#ShareAlike"/>
</cc:License>
</rdf:RDF>
</metadata>
<g id="layer1" inkscape:groupmode="layer" inkscape:label="Layer 1">
<g id="g6815">
<g id="g3296" transform="translate(57.978143,318.94882)">
<path d="M 85.298587,247.36749 C 85.298587,247.36749 47.634276,255.12191 32.125442,278.38516 C 16.616608,301.64841 4.4310954,320.48057 16.616608,339.31272 C 28.80212,358.14488 69.789753,395.80919 110.77739,399.13251 C 151.76502,402.45583 304.63781,445.65901 363.34982,437.90459 C 422.06184,430.15018 572.71908,402.45583 572.71908,402.45583 C 572.71908,402.45583 634.75442,384.73145 618.13781,350.39046 C 601.5212,316.04947 517.33039,289.4629 517.33039,289.4629"
id="path3348"
style="fill:url(#linearGradient3228);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 80.867491,287.24735 C 80.867491,287.24735 93.053004,334.88163 122.9629,339.31272 C 152.87279,343.74382 305.74558,348.17491 326.79329,347.06714 C 347.84099,345.95936 494.06714,318.26502 510.68375,311.61837 C 527.30035,304.97173 515.11484,287.24735 515.11484,287.24735 C 515.11484,287.24735 479.66608,234.0742 477.45053,225.21201 C 475.23498,216.34982 460.83392,94.4947 458.61837,81.201413 C 456.40283,67.908127 436.4629,37.998233 402.12191,35.782686 C 367.78092,33.567138 281.37456,23.597173 263.65018,30.243816 C 245.9258,36.890459 149.54947,40.213781 130.71731,62.369258 C 111.88516,84.524735 80.867491,286.13958 80.867491,287.24735 z"
id="path3346"
style="fill:url(#linearGradient3202);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 178.59568,55.443594 C 178.59568,55.443594 189.56209,66.409996 187.99546,88.342799 C 186.42883,110.2756 178.59568,284.1714 178.59568,284.1714 L 86.164584,276.33826 L 123.76368,64.843367 L 178.59568,55.443594 z"
id="path4122"
style="opacity:0.90119761;fill:url(#linearGradient3266);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path d="M 90.864471,274.77163 C 90.864471,274.77163 275.72667,296.70443 311.75913,292.00454 C 347.79159,287.30466 490.35482,260.67197 490.35482,260.67197 L 495.0547,257.53871 L 518.55413,298.27106 L 499.75459,315.50398 L 318.02565,348.40318 L 130.03019,339.00341 L 93.997728,320.20386 L 78.33144,290.43791 L 90.864471,274.77163 z"
id="path4120"
style="fill:#8f5902;fill-rule:evenodd;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 531.08716,298.27106 L 610.98523,339.00341 L 623.51826,375.03587 L 576.5194,398.5353 L 459.02224,426.73462 C 459.02224,426.73462 476.25516,433.00114 510.72099,393.83542 C 545.18682,354.6697 534.22042,298.27106 531.08716,298.27106 z"
id="path4124"
style="fill:url(#linearGradient3294);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path d="M 73.631554,273.205 C 73.631554,273.205 48.565493,284.1714 48.565493,304.53757 C 48.565493,324.90375 45.432235,356.23632 61.098523,370.33598 C 76.764811,384.43564 130.03019,398.5353 130.03019,398.5353 C 130.03019,398.5353 89.297842,343.70329 89.297842,318.63723 C 89.297842,293.57117 73.631554,270.07174 73.631554,273.205 z"
id="path4126"
style="fill:#8f5902;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path d="M 526,292 C 526,292 546,308 484,323 C 422,338 319,350 319,350 C 319,350 292,351 319,362 C 346,373 510,387 531,366 C 552,345 577,340 576,319 C 575,298 523,292 526,292 z"
id="path3166"
style="fill:#c17d11;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path d="M 80.867491,287.24735 C 80.867491,287.24735 93.053004,334.88163 122.9629,339.31272 C 152.87279,343.74382 305.74558,348.17491 326.79329,347.06714 C 347.84099,345.95936 494.06714,318.26502 510.68375,311.61837 C 527.30035,304.97173 515.11484,287.24735 515.11484,287.24735 C 515.11484,287.24735 479.66608,234.0742 477.45053,225.21201 C 475.23498,216.34982 460.83392,94.4947 458.61837,81.201413 C 456.40283,67.908127 436.4629,37.998233 402.12191,35.782686 C 367.78092,33.567138 281.37456,23.597173 263.65018,30.243816 C 245.9258,36.890459 149.54947,40.213781 130.71731,62.369258 C 111.88516,84.524735 80.867491,286.13958 80.867491,287.24735 z"
id="path2445"
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 85.298587,247.36749 C 85.298587,247.36749 47.634276,255.12191 32.125442,278.38516 C 16.616608,301.64841 4.4310954,320.48057 16.616608,339.31272 C 28.80212,358.14488 69.789753,395.80919 110.77739,399.13251 C 151.76502,402.45583 304.63781,445.65901 363.34982,437.90459 C 422.06184,430.15018 572.71908,402.45583 572.71908,402.45583 C 572.71908,402.45583 634.75442,384.73145 618.13781,350.39046 C 601.5212,316.04947 517.33039,289.4629 517.33039,289.4629"
id="path3217"
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:20;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 90.864471,274.77163 C 90.864471,274.77163 275.72667,296.70443 311.75913,292.00454 C 347.79159,287.30466 490.35482,260.67197 490.35482,260.67197 L 495.0547,257.53871 L 518.55413,298.27106 L 499.75459,315.50398 L 318.02565,348.40318 L 130.03019,339.00341 L 93.997728,320.20386 L 78.33144,290.43791 L 90.864471,274.77163 z"
id="path3268"
style="opacity:0.71556869;fill:url(#linearGradient3276);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:10;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
<path d="M 77.781746,250.8974 L 79.195959,289.08117 L 110.30866,335.75022 L 175.36248,342.82128 L 298.39906,344.2355 L 470.93312,420.60303 L 332.34019,440.40202 L 142.83557,406.46089 L 35.355339,372.51977 L 5.6568542,320.19387 L 26.870058,282.0101 L 77.781746,250.8974 z"
id="path3278"
style="opacity:0.50898204;fill:url(#linearGradient3286);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
</g>
<rect height="697.14288" id="rect5949"
style="opacity:0.50898204000000002;fill:none;fill-opacity:1;stroke:none;stroke-width:10;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
width="697.14288" x="23.428572" y="183.79076"/>
</g>
</g> </g>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Before After
Before After

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 360 KiB

After

Width:  |  Height:  |  Size: 428 KiB

Before After
Before After

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 329 KiB

Before After
Before After

View file

@ -15,7 +15,7 @@ class Configuration:
self.__configuration = configparser.ConfigParser() self.__configuration = configparser.ConfigParser()
self.__configuration_path = configuration_path self.__configuration_path = configuration_path
#print('[linspector] reading configuration file: ' + configuration_path + # print('[linspector] reading configuration file: ' + configuration_path +
# '/linspector.conf') # '/linspector.conf')
if os.path.isfile(configuration_path + '/linspector.conf'): if os.path.isfile(configuration_path + '/linspector.conf'):
try: try:
@ -35,7 +35,7 @@ class Configuration:
section_list = glob.glob(configuration_path + '/' + target_section + '/*.conf') section_list = glob.glob(configuration_path + '/' + target_section + '/*.conf')
for section_file in section_list: for section_file in section_list:
#print('reading section file: ' + section_file) # print('reading section file: ' + section_file)
configuration = configparser.ConfigParser() configuration = configparser.ConfigParser()
configuration.read(section_file, 'utf-8') configuration.read(section_file, 'utf-8')
for source_section in configuration.sections(): for source_section in configuration.sections():
@ -46,7 +46,7 @@ class Configuration:
configuration.get(source_section, configuration.get(source_section,
source_section_option)) source_section_option))
#print('configuration dump: ' + self.dump_to_ini()) # print('configuration dump: ' + self.dump_to_ini())
def dump_to_ini(self): def dump_to_ini(self):
dump = '' dump = ''

View file

@ -7,9 +7,9 @@ import datetime
import importlib import importlib
import random import random
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.schedulers.background import BackgroundScheduler
def job_function(log, monitor): def job_function(log, monitor):

View file

@ -102,7 +102,7 @@ class Log:
self.set_level(logging.INFO) self.set_level(logging.INFO)
elif log_level == "debug": elif log_level == "debug":
self.set_level(logging.DEBUG) self.set_level(logging.DEBUG)
#elif configuration.get_option('linspector', 'log_level') != 'error' != 'warning' \ # elif configuration.get_option('linspector', 'log_level') != 'error' != 'warning' \
# != 'info' != 'debug': # != 'info' != 'debug':
# logger.warning('[linspector] log level: "' + log_level + '" not found!') # logger.warning('[linspector] log level: "' + log_level + '" not found!')

View file

@ -6,11 +6,8 @@ See LICENSE.txt (MIT license).
import configparser import configparser
import hashlib import hashlib
import importlib import importlib
from datetime import datetime
from binascii import crc32 from binascii import crc32
from datetime import datetime
from linspector.core.task import Task, TaskExecutor
class Monitor: class Monitor:
@ -33,7 +30,8 @@ class Monitor:
'identifier: ' + identifier + ' to: ' + str(self.__interval)) 'identifier: ' + identifier + ' to: ' + str(self.__interval))
except Exception as err: except Exception as err:
log.warning('no default_interval found in core configuration for identifier ' + log.warning('no default_interval found in core configuration for identifier ' +
identifier + ', set to default interval 300 seconds. error: ' + str(err)) identifier + ', set to default interval 300 seconds. error: ' + str(
err))
# default interval is 300 seconds (5 minutes) if not set in the monitor # default interval is 300 seconds (5 minutes) if not set in the monitor
# configuration args or a default_interval in the core configuration. # configuration args or a default_interval in the core configuration.
self.__interval = 300 self.__interval = 300
@ -48,10 +46,10 @@ class Monitor:
# if no service is set in the monitor configuration, the service is set to misc.dummy # if no service is set in the monitor configuration, the service is set to misc.dummy
# instead. just to make Linspector run but with no real result. # instead. just to make Linspector run but with no real result.
log.debug('no service set for identifier: ' + identifier + ' setting to ' log.debug('no service set for identifier: ' + identifier + ' setting to '
'misc.dummy as ' 'misc.dummy as '
'default to ensure ' 'default to ensure '
'Linspector will run. ' 'Linspector will run. '
'error: ' + str(err)) 'error: ' + str(err))
self.__service = 'misc.dummy' self.__service = 'misc.dummy'
@ -83,7 +81,7 @@ class Monitor:
""" """
self.status = "NONE" self.status = "NONE"
self.last_execution = None self.last_execution = None
#self.monitor_information = MonitorInformation(self.monitor_id, self.hostgroup, self.host, # self.monitor_information = MonitorInformation(self.monitor_id, self.hostgroup, self.host,
# self.service) # self.service)
self.monitor_information = MonitorInformation(self.monitor_id, self.service) self.monitor_information = MonitorInformation(self.monitor_id, self.service)
@ -175,7 +173,7 @@ class Monitor:
def hex_string(self): def hex_string(self):
ret = hex(crc32(bytes(self.host + self.hostgroups + self.service, 'utf-8'))) ret = hex(crc32(bytes(self.host + self.hostgroups + self.service, 'utf-8')))
#ret = self.__hex__() # ret = self.__hex__()
if ret[0] == "-": if ret[0] == "-":
ret = ret[3:] ret = ret[3:]
else: else:
@ -198,10 +196,10 @@ class Monitor:
if execution_successful: if execution_successful:
if self.job_threshold > 0: if self.job_threshold > 0:
if "threshold_reset" in self.core and self.core["threshold_reset"]: if "threshold_reset" in self.core and self.core["threshold_reset"]:
#logger.info("Job " + self.get_monitor_id() + ", Threshold Reset") # logger.info("Job " + self.get_monitor_id() + ", Threshold Reset")
self.job_threshold = 0 self.job_threshold = 0
else: else:
#logger.info("Job " + self.get_monitor_id() + ", Threshold Decrement") # logger.info("Job " + self.get_monitor_id() + ", Threshold Decrement")
self.job_threshold -= 1 self.job_threshold -= 1
self.status = "OK" self.status = "OK"
@ -214,7 +212,7 @@ class Monitor:
self.job_threshold += 1 self.job_threshold += 1
if self.job_threshold >= service_threshold: if self.job_threshold >= service_threshold:
#logger.info("Job " + self.get_monitor_id() + ", Threshold reached!") # logger.info("Job " + self.get_monitor_id() + ", Threshold reached!")
self.status = "ERROR" self.status = "ERROR"
self.monitor_information.set_status(self.status) self.monitor_information.set_status(self.status)
@ -224,34 +222,34 @@ class Monitor:
self.__log.debug('executing task of type: ' + self.status) self.__log.debug('executing task of type: ' + self.status)
# tasks can but should not be executed here. putting them in a queue is the better # tasks can but should not be executed here. putting them in a queue is the better
# solution to execute them in a serial process. # solution to execute them in a serial process.
#TaskExecutor.instance().schedule_task(monitor_information, task) # TaskExecutor.instance().schedule_task(monitor_information, task)
def handle_call(self): def handle_call(self):
self.__log.info('handle call to monitor with identifier: ' + self.__identifier) self.__log.info('handle call to monitor with identifier: ' + self.__identifier)
#logger.debug("handle call") # logger.debug("handle call")
#logger.debug(self.service) # logger.debug(self.service)
if self.enabled: if self.enabled:
self.last_execution = None self.last_execution = None
try: try:
self.last_execution = MonitorExecution(self.get_host()) self.last_execution = MonitorExecution(self.get_host())
#self.__services[self.__service].execute(self.last_execution) # self.__services[self.__service].execute(self.last_execution)
self.__services[self.__service].execute(**self.__args) self.__services[self.__service].execute(**self.__args)
except Exception as err: except Exception as err:
self.__log.error(err) self.__log.error(err)
#self.last_execution.set_execution_end() # self.last_execution.set_execution_end()
#self.handle_threshold(self.service.get_threshold(), # self.handle_threshold(self.service.get_threshold(),
# self.last_execution.was_successful()) # self.last_execution.was_successful())
#log.info("Job " + self.get_monitor_id() + # log.info("Job " + self.get_monitor_id() +
# ", Code: " + str(self.last_execution.get_error_code()) + # ", Code: " + str(self.last_execution.get_error_code()) +
# ", Message: " + str(self.last_execution.get_message())) # ", Message: " + str(self.last_execution.get_message()))
#self.monitor_information.set_response_message( # self.monitor_information.set_response_message(
# self.last_execution.get_response_message(self)) # self.last_execution.get_response_message(self))
#self.handle_tasks(self.monitor_information) # self.handle_tasks(self.monitor_information)
else: else:
self.__log.info('job ' + self.get_monitor_id() + ' disabled') self.__log.info('job ' + self.get_monitor_id() + ' disabled')
@ -308,8 +306,8 @@ class MonitorExecution:
class MonitorInformation: class MonitorInformation:
def __init__(self, monitor_id, service): def __init__(self, monitor_id, service):
self.monitor_id = monitor_id self.monitor_id = monitor_id
#self.hostgroup = hostgroup # self.hostgroup = hostgroup
#self.host = host # self.host = host
self.service = service self.service = service
self.response_massage = None self.response_massage = None

View file

@ -4,7 +4,8 @@ Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
#see http://stackoverflow.com/questions/42558/python-and-the-singleton-pattern
# see http://stackoverflow.com/questions/42558/python-and-the-singleton-pattern
class Singleton: class Singleton:

View file

@ -4,7 +4,7 @@ Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
from queue import Queue from queue import Queue
from threading import Event, Thread from threading import Thread
from linspector.core.singleton import Singleton from linspector.core.singleton import Singleton
@ -47,7 +47,7 @@ class Task:
def get_arguments(self): def get_arguments(self):
return self._args return self._args
#def set_member(self, member): # def set_member(self, member):
# self.member = member # self.member = member
def needs_arguments(self): def needs_arguments(self):
@ -57,7 +57,7 @@ class Task:
try: try:
self.execute(job) self.execute(job)
except Exception as e: except Exception as e:
#logger.debug("Task execute failed!!!") # logger.debug("Task execute failed!!!")
raise e raise e
@ -85,7 +85,7 @@ class TaskExecutor:
msg, task = self.queue.get() msg, task = self.queue.get()
if task: if task:
self.__log.debug('starting task execution...') self.__log.debug('starting task execution...')
#task.execute(msg) # task.execute(msg)
self.queue.task_done() self.queue.task_done()
except Exception as err: except Exception as err:

View file

@ -3,7 +3,6 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
import gammu
from linspector.core.notification import Notification from linspector.core.notification import Notification

View file

@ -3,7 +3,6 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
import xmpp
from linspector.core.notification import Notification from linspector.core.notification import Notification

26
linspector/plugins/api.py Normal file
View file

@ -0,0 +1,26 @@
"""
This file is part of Linspector (https://linspector.org/)
Copyright (c) 2023 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license).
"""
# TODO: Make this a backend API using the modern FastAPI framework as a replacement for the
# traditional RPC plugin. Maybe it makes sense to maintain the RPC plugin too for simple usage by
# the Lish but I believe it makes sense to only create one backend for all clients.
from linspector.core.plugin import Plugin
def create(configuration, environment, linspector, log):
return APIPlugin(configuration, environment, linspector, log)
# TODO: check for all required configuration options and set defaults if needed.
class APIPlugin(Plugin):
def __init__(self, configuration, environment, linspector, log):
super().__init__(configuration, environment, linspector, log)
self.__configuration = configuration
self.__environment = environment
self.__linspector = linspector
self.__log = log
def run(self):
return

View file

@ -1,8 +0,0 @@
"""
This file is part of Linspector (https://linspector.org/)
Copyright (c) 2023 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license).
"""
# TODO: Make this a backend API using the modern FastAPI framework as a replacement for the
# traditional RPC plugin. Maybe it makes sense to maintain the RPC plugin too for simple usage by
# the Lish but I believe it makes sense to only create one backend for all clients.

View file

@ -3,9 +3,10 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
import cherrypy
import json import json
import cherrypy
from linspector.core.plugin import Plugin from linspector.core.plugin import Plugin
@ -29,22 +30,22 @@ class HTTPServerPlugin(Plugin):
@cherrypy.expose @cherrypy.expose
def configuration(self): def configuration(self):
return '<!DOCTYPE html><html><head><title>[monipy-' + \ return '<!DOCTYPE html><html><head><title>[monipy-' + \
self.__environment.get_env_var("__version__") + '@' + \ self.__environment.get_env_var("__version__") + '@' + \
self.__environment.get_env_var("_hostname") + '] configuration</title><meta ' + \ self.__environment.get_env_var("_hostname") + '] configuration</title><meta ' + \
'http-equiv="refresh" content="60"></head><body><pre ' + \ 'http-equiv="refresh" content="60"></head><body><pre ' + \
'style="border:2px solid black;background:#1d2021;color:#f0751a;">' + \ 'style="border:2px solid black;background:#1d2021;color:#f0751a;">' + \
json.dumps(vars(self.__configuration), sort_keys=True, indent=4) + \ json.dumps(vars(self.__configuration), sort_keys=True, indent=4) + \
'</pre></body></html>' '</pre></body></html>'
@cherrypy.expose @cherrypy.expose
def environment(self): def environment(self):
return '<!DOCTYPE html><html><head><title>[monipy-' + \ return '<!DOCTYPE html><html><head><title>[monipy-' + \
self.__environment.get_env_var("__version__") + '@' + \ self.__environment.get_env_var("__version__") + '@' + \
self.__environment.get_env_var("_hostname") + '] environment</title><meta ' + \ self.__environment.get_env_var("_hostname") + '] environment</title><meta ' + \
'http-equiv="refresh" content="60"></head><body><pre ' + \ 'http-equiv="refresh" content="60"></head><body><pre ' + \
'style="border:2px solid black;background:#1d2021;color:#f0751a;">' + \ 'style="border:2px solid black;background:#1d2021;color:#f0751a;">' + \
json.dumps(vars(self.__environment), sort_keys=True, indent=4) + \ json.dumps(vars(self.__environment), sort_keys=True, indent=4) + \
'</pre></body></html>' '</pre></body></html>'
@cherrypy.expose @cherrypy.expose
def playground(self): def playground(self):
@ -73,11 +74,11 @@ class HTTPServerPlugin(Plugin):
# 'tools.staticdir.dir': './public' # 'tools.staticdir.dir': './public'
} }
} }
#cherrypy.config.update({ # cherrypy.config.update({
# 'global': { # 'global': {
# 'engine.autoreload.on': False # 'engine.autoreload.on': False
# } # }
#}) # })
cherrypy.config.update({ cherrypy.config.update({
'global': { 'global': {
'server.socket_host': self.__configuration.get_httpserver_host(), 'server.socket_host': self.__configuration.get_httpserver_host(),
@ -87,4 +88,4 @@ class HTTPServerPlugin(Plugin):
}) })
cherrypy.tree.mount(root=None, config=conf) cherrypy.tree.mount(root=None, config=conf)
cherrypy.quickstart(self, '/', conf) cherrypy.quickstart(self, '/', conf)
#cherrypy.server.bus.exit(self) # cherrypy.server.bus.exit(self)

View file

@ -19,5 +19,5 @@ class DummyService(Service):
def execute(self, **kwargs): def execute(self, **kwargs):
self.__log.debug('DummyService object ' + str(self) + ' using kwargs: ' + str(kwargs)) self.__log.debug('DummyService object ' + str(self) + ' using kwargs: ' + str(kwargs))
#log('debug', 'dummy object @' + str(self) + str(self.__kwargs['foo'])) # log('debug', 'dummy object @' + str(self) + str(self.__kwargs['foo']))
return return

View file

@ -3,7 +3,6 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
from fritzconnection.lib.fritzstatus import FritzStatus
from linspector.core.service import Service from linspector.core.service import Service

View file

@ -3,7 +3,6 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
from fritzconnection.lib.fritzstatus import FritzStatus
from linspector.core.service import Service from linspector.core.service import Service

View file

@ -4,9 +4,10 @@ Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
import calendar import calendar
import requests
import time import time
import requests
from linspector.core.service import Service from linspector.core.service import Service

View file

@ -4,9 +4,10 @@ Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
import os import os
import paramiko
import pprint import pprint
import paramiko
from linspector.core.service import Service from linspector.core.service import Service
@ -31,9 +32,8 @@ class SSHService(Service):
client.connect('hanez.org', username='hanez') client.connect('hanez.org', username='hanez')
#self.command.call() ist dann das: # self.command.call() ist dann das:
stdin, stdout, stderr = client.exec_command('ls') stdin, stdout, stderr = client.exec_command('ls')
for line in stdout: for line in stdout:
print('... ' + line.strip('\n')) print('... ' + line.strip('\n'))
client.close() client.close()

View file

@ -3,7 +3,6 @@ This file is part of Linspector (https://linspector.org/)
Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved. Copyright (c) 2022 Johannes Findeisen <you@hanez.org>. All Rights Reserved.
See LICENSE.txt (MIT license). See LICENSE.txt (MIT license).
""" """
from pysnmp.entity.rfc3413.oneliner import cmdgen
from linspector.core.service import Service from linspector.core.service import Service