From 2384c789a78e95858e97f8e710b38ae40b471b48 Mon Sep 17 00:00:00 2001 From: Johannes Findeisen Date: Tue, 27 Sep 2022 02:28:09 +0200 Subject: [PATCH] Enabled loading of monitors in etc/, some refactoring and fixes. --- bin/linspector | 19 ++++++-- etc.example/linspector.ini | 43 +++++++++++++++++++ etc.example/monitors/.gitkeep | 0 etc.example/monitors/network1/.gitkeep | 0 etc.example/monitors/network1/gateway.ini | 17 ++++++++ etc.example/monitors/network2/.gitkeep | 0 etc.example/monitors/network2/gateway.ini | 13 ++++++ etc.example/notifications/.gitkeep | 0 etc.example/notifications/email.ini | 7 +++ etc.example/plugins/.gitkeep | 0 etc.example/plugins/httpserver.ini | 3 ++ etc.example/services/.gitkeep | 0 etc.example/tasks/.gitkeep | 0 etc/monitors/network1/gateway.ini | 4 -- etc/monitors/test/.gitkeep | 0 etc/monitors/test/test1 | 0 linspector/core/configuration.py | 15 ++++--- linspector/core/environment.py | 6 +-- linspector/core/linspector.py | 11 ++++- linspector/core/linspectord.py | 5 ++- linspector/{monitors => core}/monitor.py | 15 ++++++- linspector/{monitors => core}/monitors.py | 33 ++++++++++++-- .../{notifications => core}/notification.py | 0 .../{notifications => core}/notifications.py | 0 linspector/{plugins => core}/plugin.py | 0 linspector/{plugins => core}/plugins.py | 0 linspector/{services => core}/service.py | 0 linspector/{services => core}/services.py | 0 linspector/{tasks => core}/task.py | 0 linspector/{tasks => core}/tasks.py | 0 linspector/plugins/httpserver.py | 2 +- linspector/plugins/lish.py | 2 +- 32 files changed, 167 insertions(+), 28 deletions(-) create mode 100644 etc.example/linspector.ini create mode 100644 etc.example/monitors/.gitkeep create mode 100644 etc.example/monitors/network1/.gitkeep create mode 100644 etc.example/monitors/network1/gateway.ini create mode 100644 etc.example/monitors/network2/.gitkeep create mode 100644 etc.example/monitors/network2/gateway.ini create mode 100644 etc.example/notifications/.gitkeep create mode 100644 etc.example/notifications/email.ini create mode 100644 etc.example/plugins/.gitkeep create mode 100644 etc.example/plugins/httpserver.ini create mode 100644 etc.example/services/.gitkeep create mode 100644 etc.example/tasks/.gitkeep create mode 100644 etc/monitors/test/.gitkeep create mode 100644 etc/monitors/test/test1 rename linspector/{monitors => core}/monitor.py (69%) rename linspector/{monitors => core}/monitors.py (52%) rename linspector/{notifications => core}/notification.py (100%) rename linspector/{notifications => core}/notifications.py (100%) rename linspector/{plugins => core}/plugin.py (100%) rename linspector/{plugins => core}/plugins.py (100%) rename linspector/{services => core}/service.py (100%) rename linspector/{services => core}/services.py (100%) rename linspector/{tasks => core}/task.py (100%) rename linspector/{tasks => core}/tasks.py (100%) diff --git a/bin/linspector b/bin/linspector index 6b98dc5..0b3c857 100755 --- a/bin/linspector +++ b/bin/linspector @@ -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 ' @@ -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__': diff --git a/etc.example/linspector.ini b/etc.example/linspector.ini new file mode 100644 index 0000000..54eb817 --- /dev/null +++ b/etc.example/linspector.ini @@ -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 \ No newline at end of file diff --git a/etc.example/monitors/.gitkeep b/etc.example/monitors/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/monitors/network1/.gitkeep b/etc.example/monitors/network1/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/monitors/network1/gateway.ini b/etc.example/monitors/network1/gateway.ini new file mode 100644 index 0000000..d375bfb --- /dev/null +++ b/etc.example/monitors/network1/gateway.ini @@ -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 \ No newline at end of file diff --git a/etc.example/monitors/network2/.gitkeep b/etc.example/monitors/network2/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/monitors/network2/gateway.ini b/etc.example/monitors/network2/gateway.ini new file mode 100644 index 0000000..b3d2aa6 --- /dev/null +++ b/etc.example/monitors/network2/gateway.ini @@ -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 \ No newline at end of file diff --git a/etc.example/notifications/.gitkeep b/etc.example/notifications/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/notifications/email.ini b/etc.example/notifications/email.ini new file mode 100644 index 0000000..9d0bf9e --- /dev/null +++ b/etc.example/notifications/email.ini @@ -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 \ No newline at end of file diff --git a/etc.example/plugins/.gitkeep b/etc.example/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/plugins/httpserver.ini b/etc.example/plugins/httpserver.ini new file mode 100644 index 0000000..b832680 --- /dev/null +++ b/etc.example/plugins/httpserver.ini @@ -0,0 +1,3 @@ +[httpserver] +ip = 127.0.0.1 +port = 4242 \ No newline at end of file diff --git a/etc.example/services/.gitkeep b/etc.example/services/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc.example/tasks/.gitkeep b/etc.example/tasks/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/monitors/network1/gateway.ini b/etc/monitors/network1/gateway.ini index d375bfb..b7f786a 100644 --- a/etc/monitors/network1/gateway.ini +++ b/etc/monitors/network1/gateway.ini @@ -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 diff --git a/etc/monitors/test/.gitkeep b/etc/monitors/test/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/monitors/test/test1 b/etc/monitors/test/test1 new file mode 100644 index 0000000..e69de29 diff --git a/linspector/core/configuration.py b/linspector/core/configuration.py index fff18f6..606deb0 100644 --- a/linspector/core/configuration.py +++ b/linspector/core/configuration.py @@ -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) diff --git a/linspector/core/environment.py b/linspector/core/environment.py index 7b41ced..39abbde 100644 --- a/linspector/core/environment.py +++ b/linspector/core/environment.py @@ -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 diff --git a/linspector/core/linspector.py b/linspector/core/linspector.py index c84f5ec..e10494a 100644 --- a/linspector/core/linspector.py +++ b/linspector/core/linspector.py @@ -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()) diff --git a/linspector/core/linspectord.py b/linspector/core/linspectord.py index f3d2645..cbfe595 100644 --- a/linspector/core/linspectord.py +++ b/linspector/core/linspectord.py @@ -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 diff --git a/linspector/monitors/monitor.py b/linspector/core/monitor.py similarity index 69% rename from linspector/monitors/monitor.py rename to linspector/core/monitor.py index f257064..10d5902 100644 --- a/linspector/monitors/monitor.py +++ b/linspector/core/monitor.py @@ -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 diff --git a/linspector/monitors/monitors.py b/linspector/core/monitors.py similarity index 52% rename from linspector/monitors/monitors.py rename to linspector/core/monitors.py index 0631dd2..2ccdef0 100644 --- a/linspector/monitors/monitors.py +++ b/linspector/core/monitors.py @@ -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 diff --git a/linspector/notifications/notification.py b/linspector/core/notification.py similarity index 100% rename from linspector/notifications/notification.py rename to linspector/core/notification.py diff --git a/linspector/notifications/notifications.py b/linspector/core/notifications.py similarity index 100% rename from linspector/notifications/notifications.py rename to linspector/core/notifications.py diff --git a/linspector/plugins/plugin.py b/linspector/core/plugin.py similarity index 100% rename from linspector/plugins/plugin.py rename to linspector/core/plugin.py diff --git a/linspector/plugins/plugins.py b/linspector/core/plugins.py similarity index 100% rename from linspector/plugins/plugins.py rename to linspector/core/plugins.py diff --git a/linspector/services/service.py b/linspector/core/service.py similarity index 100% rename from linspector/services/service.py rename to linspector/core/service.py diff --git a/linspector/services/services.py b/linspector/core/services.py similarity index 100% rename from linspector/services/services.py rename to linspector/core/services.py diff --git a/linspector/tasks/task.py b/linspector/core/task.py similarity index 100% rename from linspector/tasks/task.py rename to linspector/core/task.py diff --git a/linspector/tasks/tasks.py b/linspector/core/tasks.py similarity index 100% rename from linspector/tasks/tasks.py rename to linspector/core/tasks.py diff --git a/linspector/plugins/httpserver.py b/linspector/plugins/httpserver.py index 561fe79..1bec6c6 100644 --- a/linspector/plugins/httpserver.py +++ b/linspector/plugins/httpserver.py @@ -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') diff --git a/linspector/plugins/lish.py b/linspector/plugins/lish.py index cb146e4..a4ec8cd 100644 --- a/linspector/plugins/lish.py +++ b/linspector/plugins/lish.py @@ -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')