Enabled loading of monitors in etc/, some refactoring and fixes.

This commit is contained in:
Johannes Findeisen 2022-09-27 02:28:09 +02:00
commit 2384c789a7
32 changed files with 167 additions and 28 deletions

View file

@ -31,6 +31,8 @@ from logging import getLogger
from linspector.core.configuration import Configuration
from linspector.core.environment import Environment
from linspector.core.linspector import Linspector
from linspector.core.linspectord import Linspectord
from linspector.core.monitors import Monitors
__version__ = '0.1'
__author__ = 'Johannes Findeisen <you@hanez.org>'
@ -55,15 +57,24 @@ def parse_args():
def main():
args = parse_args()
environment = Environment()
notifications = {}
services = {}
try:
configuration = Configuration(args.configuration_path)
configuration.dump_to_ini()
configuration = Configuration(args.configuration_path, environment)
# configuration.dump_to_ini()
except Exception as err:
logger.error(str('[uplink] configuration error: {0}'.format(err)))
sys.exit(1)
environment = Environment(configuration)
linspector = Linspector(configuration, environment)
monitors = Monitors(configuration, environment, notifications, services)
linspector = Linspector(configuration, environment, monitors)
#linspector.print_monitors_monitor_identifiers()
# so, if Linspector should start in Daemon mode, do thi here...
#Linspectord(configuration, environment, linspector).execute()
if __name__ == '__main__':

View file

@ -0,0 +1,43 @@
; all you need to know: https://docs.python.org/3/library/configparser.html ... ;)
[linspector]
; report core errors to the following users
error_receivers = admin@example.com
log_file = ~/code/linspector/log/linspector.log
log_level= verbose
log_count = 5
log_size = 10485760
pid_file = /var/run/user/1000/linspector.pid
; default delimiters '=' and ':' should be changed to ',' to be more native
plugins = HTTPServer
tasks = MariaDB:Logger
; maybe the run_mode is obsolete because this will be a daemon but maybe it is useful for one time execution?
; in uplink the available run_modes were cron, daemon and foreground
run_mode = cron
; every notification can be configured in it's own ini file in etc/notifications; there no notification name as prefix
; is needed. see email example.
[notifications]
; values can be overridden in each defined monitor
sms_receivers = +number1:+number2
sms_configuration_file = ~/linspector/etc/gammurc
; retry to send interval and number of retries if something failed
sms_resend = 10
sms_resend_count = 5
email_resend = 10
; every plugin can be configured in it's own ini file in etc/plugins; there no plugin name as prefix is needed. see
; httpserver example.
[plugins]
; if types can or must be configured before use; for now no use case seen.
; every type can be configured in it's own ini file in etc/types; there no type name as prefix is not needed.
[services]
speedtest_interval = 3600
speedtest_url = https://go.microsoft.com/fwlink/?Linkid=850641
[tasks]
mariadb_database = linspector
mariadb_host = 10.0.0.254
mariadb_password = PASSWORD
mariadb_port": 3306
mariadb_user = USER

View file

View file

View file

@ -0,0 +1,17 @@
[main]
; identifiers must be unique in the whole configuration so maybe it is better to create a random string for this
; dynamically. identifiers should maybe a checksum of some options so they will not change when small changes to
; the configurations changes and will remain even when doing a fresh install.
identifier = cable
service = Fritzbox
interval = 60
# default delimiters '=' and ':' should be changed to ',' to be more native
notifications = SMS:Email
; values from main configuration can be overridden for each defined monitor
email_receivers = admin@example.com:fallback@example.com
sms_receivers = +329084320984:+39804932409
tasks = None
host = 192.168.0.1
user = USERNAME
password = PASSWORD
info = Cable Provider

View file

View file

@ -0,0 +1,13 @@
[main]
identifier = dsl
service = Fritzbox
interval = 60
# default delimiters '=' and ':' should be changed to ',' to be more native
notifications = SMS:Email
email_receivers = admin@example.com:fallback@example.com
sms_receivers = +329084320984:+39804932409
tasks = MariaDB:Logger:Redis
host = 192.168.1.1
user = USERNAME
password = PASSWORD
info = Cable Provider

View file

View file

@ -0,0 +1,7 @@
[email]
resend = 20
smtp_host = mail.example.com
smtp_port = 25
smtp_password = PASSWORD
smtp_user = alerts@example.com
receivers = admin@example.com

View file

View file

@ -0,0 +1,3 @@
[httpserver]
ip = 127.0.0.1
port = 4242

View file

View file

View file

@ -1,8 +1,4 @@
[main]
; identifiers must be unique in the whole configuration so maybe it is better to create a random string for this
; dynamically. identifiers should maybe a checksum of some options so they will not change when small changes to
; the configurations changes and will remain even when doing a fresh install.
identifier = cable
service = Fritzbox
interval = 60
# default delimiters '=' and ':' should be changed to ',' to be more native

View file

0
etc/monitors/test/test1 Normal file
View file

View file

@ -34,8 +34,10 @@ logger = getLogger('linspector')
# options in the "monipy" section of monipy.ini.
class Configuration:
def __init__(self, configuration_path):
def __init__(self, configuration_path, environment):
self.__configuration = configparser.ConfigParser()
self.__configuration_path = configuration_path
self.__environment = environment
if os.path.isfile(configuration_path + '/linspector.ini'):
try:
@ -55,7 +57,7 @@ class Configuration:
section_list = glob.glob(configuration_path + '/' + target_section + '/*.ini')
for section_file in section_list:
print("-->"+section_file)
#print("-->"+section_file)
configuration = configparser.ConfigParser()
configuration.read(section_file, 'utf-8')
for source_section in configuration.sections():
@ -78,16 +80,17 @@ class Configuration:
print(option + " = " + self.__configuration.get(section, option))
i = 1
def get_configuration_path(self):
return self.__configuration_path
def get_option(self, section, option):
if self.__configuration.has_option(section, option):
return self.__configuration.get(section, option)
else:
return None
# this function can be called by notifications, plugins etc. to set their default values if not
# configured. since all objects have access to the configuration this should not be done from
# any other place because it can break linspector.
# maybe it can be used for dynamic runtime configuration later but need to think about it.
# this function should be used with care because it edits the main configuration. maybe it can
# be used for dynamic runtime configuration later but i need to think about it.
def set_option(self, section, option, value):
if not self.__configuration.has_option(section, option):
self.__configuration.set(section, option, value)

View file

@ -31,9 +31,7 @@ class Environment:
Object for storing environment variables at runtime. These variables must not affect the
stability or runtime of Linspector.
"""
def __init__(self, configuration):
self.__configuration = configuration
def __init__(self):
self.__env = {}
def get_env_var(self, key):
@ -51,6 +49,6 @@ class Environment:
def set_env_var(self, key, value):
if self.__env[key]:
logger.info('environment var "' + key + ' existed and was overwritten.')
logger.warning('environment var "' + key + ' existed and was overwritten!')
self.__env[key] = value

View file

@ -28,6 +28,15 @@ logger = getLogger('linspector')
class Linspector:
def __init__(self, configuration, environment):
def __init__(self, configuration, environment, monitors):
self.__configuration = configuration
self.__environment = environment
self.__monitors = monitors
# this function is just for testing purposes and can be removed some day
def print_monitors_monitor_identifiers(self):
# example on how to access the monitor objects in monitors
monitors = self.__monitors.get_monitors()
#print(monitors)
for monitor in monitors:
print(monitors.get(monitor).get_identifier())

View file

@ -27,9 +27,10 @@ from linspector.core.daemon import Daemon
logger = getLogger('linspector')
class Linspector(Daemon):
class Linspectord(Daemon):
def __init__(self, configuration, environment):
def __init__(self, configuration, environment, linspector):
super().__init__(configuration.get_option('linspector', 'pid_file'))
self.__configuration = configuration
self.__environment = environment
self.__linspector = linspector

View file

@ -21,6 +21,9 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
from linspector.core.notifications import Notifications
from linspector.core.service import Service
from linspector.core.services import Services
from logging import getLogger
logger = getLogger('linspector')
@ -28,6 +31,14 @@ logger = getLogger('linspector')
class Monitor:
def __init__(self, configuration, environment):
def __init__(self, configuration, environment, identifier, monitor_configuration, notifications,
services):
self.__configuration = configuration
self._environment = environment
self.__environment = environment
self.__identifier = identifier
self.__monitor_configuration = monitor_configuration
self.__notifications = notifications
self.__services = services
def get_identifier(self):
return self.__identifier

View file

@ -21,16 +21,43 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
import configparser
import glob
import os
from linspector.core.monitor import Monitor
from logging import getLogger
logger = getLogger('linspector')
# monitors could, should be added (and maybe changed) at runtime to add new monitors without
# monitors may could / should be added (and maybe changed) at runtime to add new monitors without
# restarting the daemon. maybe add a reset function to each monitor to reset the monitor at runtime
# when changed dynamically.
class Monitors:
def __init__(self, configuration, environment):
def __init__(self, configuration, environment, notifications, services):
self.__configuration = configuration
self._environment = environment
self.__environment = environment
self.__monitors = {}
monitor_groups = os.listdir(self.__configuration.get_configuration_path() + '/monitors/')
print(monitor_groups)
for monitor_group in monitor_groups:
monitors_file_list = glob.glob(self.__configuration.get_configuration_path() +
'/monitors/' + monitor_group + '/*.ini')
for monitor_file in monitors_file_list:
monitor_configuration = configparser.ConfigParser()
monitor_configuration.read(monitor_file, 'utf-8')
identifier = monitor_group + '_' + os.path.splitext(os.path.basename(
monitor_file))[0]
self.__monitors[identifier] = Monitor(configuration, environment, identifier,
monitor_configuration, notifications,
services)
def get_monitors(self):
return self.__monitors

View file

@ -25,7 +25,7 @@ import cherrypy
import json
from logging import getLogger
from linspector.plugins.plugin import Plugin
from linspector.core.plugin import Plugin
logger = getLogger('linspector')

View file

@ -22,7 +22,7 @@ OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
from logging import getLogger
from linspector.plugins.plugin import Plugin
from linspector.core.plugin import Plugin
logger = getLogger('linspector')