commit 0c6455515565cd6d36533ea81e5e811c7ecaeee1 Author: Johannes Findeisen Date: Sun Sep 25 00:39:51 2022 +0200 Initial commit after complete rewrite of Linspector. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d1b1e63 --- /dev/null +++ b/.gitignore @@ -0,0 +1,245 @@ +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# ---> Linux +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# ---> JetBrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# ---> Lua +# Compiled Lua sources +luac.out + +# luarocks build files +*.src.rock +*.zip +*.tar.gz + +# Object files +*.o +*.os +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo +*.def +*.exp + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + + +/monipy.iml +/.idea/ +!/MANIFEST diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..f8444f5 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,6 @@ +* Findeisen, Johannes + Founder, core developer and maintainer. + Email: you@hanez.org + Homepage: http://hanez.org/ + Git: https://git.unixpeople.org/hanez + GitHub: https://github.com/hanez/> diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..e69de29 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bf877cd --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..d097e2c --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# Linspector Infrastructure and System Monitoring + +#### Linspector is not some program expecting computer to run. + +The idea is based on a software I developed in 2010 or so. The name of the software is +[Linspector](https://linspector.org/) but the implementation was just too +complicated. The idea still remains so here the rebirth of Linspector. + +This is implemented in an old-fashioned way for easy understanding without cloud +and such stuff... Hope it will become useful for someone at some day and not only for +me. Just give me some amount of time for the first usable release... ;) + +## About + +**Linspector** contains some tools and a daemon to monitor your infrastructure. It +collects data for statistics and sends alerts in case of errors. + +This project is at a very early stage of development it is not able for usage. +I design the software actually and try to convert my ideas to software. Code +nearly does not exist. + +## Development + +### To do + +**Everything!** :) Just outlining the idea and creating code and structure skeletons +at the moment! + +### Ideas + +- MAYBE rename this project to linspector and see it as an update. This is a nice idea +because [Linspector](https://linspector.org/) has its GitHub organisation, +domain etc. And all I do here is +a better Linspector. Even all nice and useful features and ideas from Linspector but +also uplink should be reimplemented here. - DONE! + +- Think about adding [APScheduler](https://pypi.org/project/APScheduler/) for +scheduling execution of the monitors instead of a self constructed thread +structure... was very nice to get the job done in Linspector. + +### Manifest + +- 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 +alternative is available. +- The core of Linspector should not use 3rd party libraries. only plugins, +notifications and types may use other libraries. But coping code into the +source tree is ok when respecting the license. Not using 3rd party libraries +should always be preferred though. +- Inline comment should be all lowercase. Descriptions and documentation comments +must be natural language. + +### Version numbering + +According to: [https://wiki.unixpeople.org/linux_kernel_version_numbering](https://wiki.unixpeople.org/linux_kernel_version_numbering) + +**MAJOR**.**FEATURE**.**MINOR**.**FIXES** + +- **MAJOR** changes _can_ change the API. The lesser, the better. +- **FEATURE** changes can, but _should_ not break the API. New features are placed + here. It _expects_ a complete documentation. +- **MINOR** changes are "just-in-time" changes or small enhancements which _should_ + not affect the documentation and _must_ not break the API. +- **FIXES** _must_ never affect anything else then stability or security. + +## License + +### MIT License + +Copyright (c) 2008 - 2022 Johannes Findeisen <you@hanez.org> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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. diff --git a/bin/__init__.py b/bin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/bin/linspector b/bin/linspector new file mode 100755 index 0000000..6b98dc5 --- /dev/null +++ b/bin/linspector @@ -0,0 +1,70 @@ +#!/usr/bin/python3 -d + +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 argparse +import sys + +from logging import getLogger + +from linspector.core.configuration import Configuration +from linspector.core.environment import Environment +from linspector.core.linspector import Linspector + +__version__ = '0.1' +__author__ = 'Johannes Findeisen ' + +logger = getLogger('linspector') + + +def parse_args(): + parser = argparse.ArgumentParser( + description='linspector is a infrastructure monitoring daemon and toolchain.', + epilog='author: ' + __author__, + prog='linspector') + + parser.add_argument('configuration_path', metavar='CONFIGURATION_PATH', + help='the configuration path to use') + + parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + str(__version__)) + + return parser.parse_args() + + +def main(): + args = parse_args() + + try: + configuration = Configuration(args.configuration_path) + 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) + + +if __name__ == '__main__': + main() diff --git a/etc/linspector/linspector.ini b/etc/linspector/linspector.ini new file mode 100644 index 0000000..3f3fc59 --- /dev/null +++ b/etc/linspector/linspector.ini @@ -0,0 +1,47 @@ +; all you need to know: https://docs.python.org/3/library/configparser.html ... ;) +; manifest: +; - no inline comments so every available character can be used in values +; - values can be overridden in each monitor +; - file names are not important but section names and key names. +; - comments can be inserted using ',' or '#' +[linspector] +; report core errors to the following users +error_receivers = admin@example.com +log_file = ~/code/linspector/log/uplink.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,mariadb,speedtest +; 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] +; some values can be overridden in each defined monitor +sms_receivers = +34324234234:+324242344 +sms_configuration_file = ~/code/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] +mariadb_database = linspector +mariadb_host = 10.0.0.254 +mariadb_password = 3qx7HfrxGNM83lqN +mariadb_port": 3306 +mariadb_user = uplink + +speedtest_interval = 3600 +speedtest_url = https://go.microsoft.com/fwlink/?Linkid=850641 + +; 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. +[types] +foo = bar \ No newline at end of file diff --git a/etc/linspector/monitors/.gitkeep b/etc/linspector/monitors/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/linspector/monitors/network1/.gitkeep b/etc/linspector/monitors/network1/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/linspector/monitors/network1/gateway.ini b/etc/linspector/monitors/network1/gateway.ini new file mode 100644 index 0000000..2dc14ab --- /dev/null +++ b/etc/linspector/monitors/network1/gateway.ini @@ -0,0 +1,14 @@ +[main] +; identifiers must be unique in the whole configuration so maybe it is better to create a random string for this +; dynamically. +identifier = cable +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 +host = 192.168.0.1 +user = USERNAME +password = PASSWORD +info = Cable Provider \ No newline at end of file diff --git a/etc/linspector/monitors/network2/.gitkeep b/etc/linspector/monitors/network2/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/linspector/monitors/network2/gateway.ini b/etc/linspector/monitors/network2/gateway.ini new file mode 100644 index 0000000..0eb8074 --- /dev/null +++ b/etc/linspector/monitors/network2/gateway.ini @@ -0,0 +1,12 @@ +[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 +host = 192.168.1.1 +user = USERNAME +password = PASSWORD +info = Cable Provider diff --git a/etc/linspector/notifications/.gitkeep b/etc/linspector/notifications/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/linspector/notifications/email.ini b/etc/linspector/notifications/email.ini new file mode 100644 index 0000000..215d9a9 --- /dev/null +++ b/etc/linspector/notifications/email.ini @@ -0,0 +1,7 @@ +[email] +resend = 20 +smtp_host = mail.example.com +smtp_port = 25 +smtp_password = k4509knsd09 +smtp_user = alert@hanez.org +receivers = admin@example.com \ No newline at end of file diff --git a/etc/linspector/plugins/.gitkeep b/etc/linspector/plugins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/etc/linspector/plugins/httpserver.ini b/etc/linspector/plugins/httpserver.ini new file mode 100644 index 0000000..b832680 --- /dev/null +++ b/etc/linspector/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/linspector/types/.gitkeep b/etc/linspector/types/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/linspector.iml b/linspector.iml new file mode 100644 index 0000000..ad3c0a3 --- /dev/null +++ b/linspector.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/linspector/__init__.py b/linspector/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/linspector/core/configuration.py b/linspector/core/configuration.py new file mode 100644 index 0000000..7d2a6f3 --- /dev/null +++ b/linspector/core/configuration.py @@ -0,0 +1,86 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. do this only for +# options in the "monipy" section of monipy.ini. +class Configuration: + + def __init__(self, configuration_path): + self.__configuration = configparser.ConfigParser() + + if os.path.isfile(configuration_path + '/linspector.ini'): + self.__configuration.read(configuration_path + '/linspector.ini', 'utf-8') + + # add keys and values from notifications, plugins and types defined in their subdir ini + # files. + for target_section in ['notifications', 'plugins', 'types']: + # check if section exists before adding content. if not exists add the section. + if not self.__configuration.has_section(target_section): + self.__configuration.add_section(target_section) + + section_list = glob.glob(configuration_path + '/linspector/' + target_section + '/*') + for section_file in section_list: + configuration = configparser.ConfigParser() + configuration.read(section_file, 'utf-8') + for source_section in configuration.sections(): + source_section_options = configuration.options(source_section) + for source_section_option in source_section_options: + self.__configuration.set(target_section, source_section + '_' + + source_section_option, + configuration.get(source_section, + source_section_option)) + + def dump_to_ini(self): + i = 0 + for section in self.__configuration.sections(): + if i < 1: + print('[' + section + ']') + else: + print('\n[' + section + ']') + options = self.__configuration.options(section) + for option in options: + print(option + " = " + self.__configuration.get(section, option)) + i = 1 + + 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 and types to set a default value if not + # configured. since all objects have access to the configuration this should not be done from + # any other place because it can break monipy. + # maybe it can be used for dynamic runtime configuration later but 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/daemon.py b/linspector/core/daemon.py new file mode 100644 index 0000000..ba9a7d2 --- /dev/null +++ b/linspector/core/daemon.py @@ -0,0 +1,147 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 atexit +import os +import signal +import sys +import time + +from logging import getLogger + +logger = getLogger('linspector') + + +class Daemon: + # subclass the daemon class and override the run() method. + + def __init__(self, pid_file): + self.__pid_file = pid_file + + def daemonize(self): + # daemonize the class using the UNIX double fork mechanism. + + # do first fork. + try: + pid = os.fork() + if pid > 0: + # exit first parent. + sys.exit(0) + except OSError as err: + logger.error(str('fork #1 failed: {0}'.format(err))) + sys.exit(1) + + # decouple from parent environment. + os.chdir('/') + os.setsid() + os.umask(0) + + # do second fork. + try: + pid = os.fork() + if pid > 0: + # Exit from second parent. + sys.exit(0) + except OSError as err: + logger.error(str('fork #2 failed: {0}'.format(err))) + sys.exit(1) + + # redirect standard file descriptors. + sys.stdout.flush() + sys.stderr.flush() + si = open(os.devnull, 'r') + so = open(os.devnull, 'a+') + se = open(os.devnull, 'a+') + + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + + # write pid file. + atexit.register(self.delete_pid) + + pid = str(os.getpid()) + with open(self.__pid_file, 'w+') as f: + f.write(pid + '\n') + + def delete_pid(self): + os.remove(self.__pid_file) + + def start(self): + # start the daemon. check for a pidfile to see if the daemon already runs before. + + try: + with open(self.__pid_file, 'r') as pf: + pid = int(pf.read().strip()) + except IOError: + pid = None + + if pid: + message = 'pid_file {0} already exist. daemon already running?' + logger.error(str(message.format(self.__pid_file))) + sys.exit(1) + + # start the daemon. + self.daemonize() + self.run() + + def stop(self): + # stop the daemon. + + # get the pid from the pid file. + try: + with open(self.__pid_file, 'r') as pf: + pid = int(pf.read().strip()) + except IOError: + pid = None + + if not pid: + message = 'pid_file {0} does not exist. daemon not running?' + logger.error(str(message.format(self.__pid_file))) + return # not an error in a restart + + # try killing the daemon process. + try: + while 1: + os.kill(pid, signal.SIGTERM) + time.sleep(0.1) + except OSError as err: + e = str(err.args) + if e.find('no such process') > 0: + if os.path.exists(self.__pid_file): + os.remove(self.__pid_file) + else: + logger.error(str(err.args)) + sys.exit(1) + + def restart(self): + # restart the daemon. + + self.stop() + self.start() + + def run(self): + """ + you should override this method when you subclass daemon. it will be called after the + process has been daemonized by start() or restart(). + """ diff --git a/linspector/core/environment.py b/linspector/core/environment.py new file mode 100644 index 0000000..1b64a81 --- /dev/null +++ b/linspector/core/environment.py @@ -0,0 +1,56 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Environment: + """ + Object for storing environment variables at runtime. These variables must not affect the + stability of monipy. + """ + def __init__(self, configuration): + self.__configuration = configuration + + self.__env = {} + + def get_env_var(self, key): + if key in self.__env: + return self.__env[key] + else: + logger.info('environment var "' + key + '" not found! could be that it is set later at ' + 'runtime. if you encounter any errors ' + 'executing monipyd, something is wrong in the ' + 'logic of the code. please consider reporting ' + 'this as a bug! btw. INFO is not an ERROR! ' + 'monipyd should work even with missing ' + 'environment variables.') + return None + + def set_env_var(self, key, value): + if self.__env[key]: + logger.info('environment var "' + key + ' existed and was overwritten.') + + self.__env[key] = value diff --git a/linspector/core/linspector.py b/linspector/core/linspector.py new file mode 100644 index 0000000..c84f5ec --- /dev/null +++ b/linspector/core/linspector.py @@ -0,0 +1,33 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Linspector: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/linspectord.py b/linspector/core/linspectord.py new file mode 100644 index 0000000..f3d2645 --- /dev/null +++ b/linspector/core/linspectord.py @@ -0,0 +1,35 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.daemon import Daemon + +logger = getLogger('linspector') + + +class Linspector(Daemon): + + def __init__(self, configuration, environment): + super().__init__(configuration.get_option('linspector', 'pid_file')) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/logger.py b/linspector/core/logger.py new file mode 100644 index 0000000..60706dc --- /dev/null +++ b/linspector/core/logger.py @@ -0,0 +1,39 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +# The logger can be used by any monitor to write arbitrary data to any arbitrary place. +# Need to think about this more but some monitors are or can collect more data than needed for +# running monipyd. This enables longtime storage of collected data like in uplink. +# Maybe this can be archived by storing an arbitrary JSON string in a none defined field in the +# database. then maybe redis can be used for everything. Storing data should be optional for +# running monipyd. +class Logger: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/model.py b/linspector/core/model.py new file mode 100644 index 0000000..619f442 --- /dev/null +++ b/linspector/core/model.py @@ -0,0 +1,34 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Model: + + def __init__(self, configuration, environment): + super().__init__() + self.__configuration = configuration + self._environment = environment diff --git a/linspector/core/monitor.py b/linspector/core/monitor.py new file mode 100644 index 0000000..f257064 --- /dev/null +++ b/linspector/core/monitor.py @@ -0,0 +1,33 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Monitor: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self._environment = environment diff --git a/linspector/core/monitors.py b/linspector/core/monitors.py new file mode 100644 index 0000000..0631dd2 --- /dev/null +++ b/linspector/core/monitors.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +# monitors 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): + self.__configuration = configuration + self._environment = environment diff --git a/linspector/core/notification.py b/linspector/core/notification.py new file mode 100644 index 0000000..f1e480b --- /dev/null +++ b/linspector/core/notification.py @@ -0,0 +1,33 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Notification: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/notifications.py b/linspector/core/notifications.py new file mode 100644 index 0000000..ef6da94 --- /dev/null +++ b/linspector/core/notifications.py @@ -0,0 +1,34 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Notifications: + + def __init__(self, configuration, environment): + super().__init__() + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/plugin.py b/linspector/core/plugin.py new file mode 100644 index 0000000..342f03b --- /dev/null +++ b/linspector/core/plugin.py @@ -0,0 +1,33 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Plugin: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/plugins.py b/linspector/core/plugins.py new file mode 100644 index 0000000..609abbd --- /dev/null +++ b/linspector/core/plugins.py @@ -0,0 +1,34 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Plugins: + + def __init__(self, configuration, environment): + super().__init__() + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/type.py b/linspector/core/type.py new file mode 100644 index 0000000..b563291 --- /dev/null +++ b/linspector/core/type.py @@ -0,0 +1,33 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Type: + + def __init__(self, configuration, environment): + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/core/types.py b/linspector/core/types.py new file mode 100644 index 0000000..0fd30af --- /dev/null +++ b/linspector/core/types.py @@ -0,0 +1,34 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger + +logger = getLogger('linspector') + + +class Types: + + def __init__(self, configuration, environment): + super().__init__() + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/notications/__init__.py b/linspector/notications/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/linspector/notications/email.py b/linspector/notications/email.py new file mode 100644 index 0000000..7e074ee --- /dev/null +++ b/linspector/notications/email.py @@ -0,0 +1,35 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.notification import Notification + +logger = getLogger('linspector') + + +class EmailNotification(Notification): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/notications/sms.py b/linspector/notications/sms.py new file mode 100644 index 0000000..592df07 --- /dev/null +++ b/linspector/notications/sms.py @@ -0,0 +1,35 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.notification import Notification + +logger = getLogger('linspector') + + +class SmsNotification(Notification): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/plugins/__init__.py b/linspector/plugins/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/linspector/plugins/httpserver.py b/linspector/plugins/httpserver.py new file mode 100644 index 0000000..1bec6c6 --- /dev/null +++ b/linspector/plugins/httpserver.py @@ -0,0 +1,106 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 cherrypy +import json + +from logging import getLogger +from linspector.core.plugin import Plugin + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class HTTPServerPlugin(Plugin): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment + + @cherrypy.expose + def index(self): + return 'Hello world!' + + @cherrypy.expose + def configuration(self): + return '[monipy-' + \ + self.__environment.get_env_var("__version__") + '@' + \ + self.__environment.get_env_var("_hostname") + '] configuration
' + \
+               json.dumps(vars(self.__configuration), sort_keys=True, indent=4) + \
+               '
' + + @cherrypy.expose + def environment(self): + return '[monipy-' + \ + self.__environment.get_env_var("__version__") + '@' + \ + self.__environment.get_env_var("_hostname") + '] environment
' + \
+               json.dumps(vars(self.__environment), sort_keys=True, indent=4) + \
+               '
' + + @cherrypy.expose + def playground(self): + return 'My Playground!' + + def run_server(self): + conf = { + '/': { + # 'tools.sessions.on': True, + # 'tools.staticdir.root': os.path.abspath(os.getcwd()) + 'tools.response_headers.on': True, + 'tools.response_headers.headers': [('Content-Type', 'text/plain')], + }, + '/configuration': { + # 'request.dispatch': cherrypy.dispatch.MethodDispatcher(), + 'tools.response_headers.on': True, + 'tools.response_headers.headers': [('Content-Type', 'text/html')], + }, + '/environment': { + # 'request.dispatch': cherrypy.dispatch.MethodDispatcher(), + 'tools.response_headers.on': True, + 'tools.response_headers.headers': [('Content-Type', 'text/html')], + }, + '/playground': { + # 'tools.staticdir.on': True, + # 'tools.staticdir.dir': './public' + } + } + #cherrypy.config.update({ + # 'global': { + # 'engine.autoreload.on': False + # } + #}) + cherrypy.config.update({ + 'global': { + 'server.socket_host': self.__configuration.get_httpserver_host(), + 'server.socket_port': self.__configuration.get_httpserver_port(), + 'environment': 'production' + } + }) + cherrypy.tree.mount(root=None, config=conf) + cherrypy.quickstart(self, '/', conf) + #cherrypy.server.bus.exit(self) diff --git a/linspector/plugins/mariadb.py b/linspector/plugins/mariadb.py new file mode 100644 index 0000000..c5f09ed --- /dev/null +++ b/linspector/plugins/mariadb.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.plugin import Plugin + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class MariadbPlugin(Plugin): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/plugins/redis.py b/linspector/plugins/redis.py new file mode 100644 index 0000000..83364b9 --- /dev/null +++ b/linspector/plugins/redis.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.plugin import Plugin + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class RedisPlugin(Plugin): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/plugins/sqlite.py b/linspector/plugins/sqlite.py new file mode 100644 index 0000000..e2ccde2 --- /dev/null +++ b/linspector/plugins/sqlite.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.plugin import Plugin + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class SqlitePlugin(Plugin): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/services/__init__.py b/linspector/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/linspector/services/fritzbox.py b/linspector/services/fritzbox.py new file mode 100644 index 0000000..f07b4e7 --- /dev/null +++ b/linspector/services/fritzbox.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.monitor import Monitor + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class FritzboxMonitor(Monitor): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/services/ping.py b/linspector/services/ping.py new file mode 100644 index 0000000..f89c596 --- /dev/null +++ b/linspector/services/ping.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.monitor import Monitor + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class PingMonitor(Monitor): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/services/port.py b/linspector/services/port.py new file mode 100644 index 0000000..6614e6e --- /dev/null +++ b/linspector/services/port.py @@ -0,0 +1,36 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 logging import getLogger +from linspector.core.monitor import Monitor + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class PortType(Monitor): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment diff --git a/linspector/services/speedtest.py b/linspector/services/speedtest.py new file mode 100644 index 0000000..bf9ece2 --- /dev/null +++ b/linspector/services/speedtest.py @@ -0,0 +1,96 @@ +""" +This file is part of Linspector (https://linspector.org/) +Copyright (c) 2022 Johannes Findeisen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice (including the next +paragraph) shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS +OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +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 calendar +import requests +import time + +from logging import getLogger + + +from linspector.core.monitor import Monitor + +logger = getLogger('linspector') + + +# TODO: check for all required configuration options and set defaults if needed. +class SpeedtestMonitor(Monitor): + + def __init__(self, configuration, environment): + super().__init__(configuration, environment) + self.__configuration = configuration + self.__environment = environment + + self.__speedtest_maximum_speed = None + self.__speedtest_average_speed = None + self.__speedtest_time_elapsed = None + + def execute(self): + while True: + tmp_time = time.localtime(calendar.timegm(time.gmtime())) + self.__environment.set_env_var('_speedtest_last_run_date', + time.strftime('%Y-%m-%d %H:%M:%S', + tmp_time)) + + self.__environment.set_env_var('_speedtest_last_run_timestamp', + calendar.timegm(time.gmtime())) + + start = time.perf_counter() + request = requests.get(self.__configuration.get_speedtest_url(), stream=True) + size = int(request.headers.get('Content-Length')) + downloaded = 0.0 + total_mbps = 0.0 + maximum_speed = 0.0 + total_chunks = 0.0 + + if size is not None: + for chunk in request.iter_content(1024 * 1024): + downloaded += len(chunk) + # megabytes per second + mbps = downloaded / (time.perf_counter() - start) / (1024 * 1024) + if mbps > maximum_speed: + maximum_speed = mbps + total_chunks += 1 + total_mbps += mbps + + self.__speedtest_average_speed = total_mbps / total_chunks + self.__environment.set_env_var('_speedtest_average_speed_megabyte_per_second', + str(round(self.__speedtest_average_speed))) + + self.__speedtest_maximum_speed = maximum_speed + self.__environment.set_env_var('_speedtest_maximum_speed_megabyte_per_second', + str(round(self.__speedtest_maximum_speed))) + + self.__speedtest_time_elapsed = time.perf_counter() - start + self.__environment.set_env_var('_speedtest_time_elapsed', + str(self.__speedtest_time_elapsed)) + logger.info('speedtest average: ' + str(self.__speedtest_average_speed) + + ', max: ' + str(self.__speedtest_maximum_speed) + + ', time: ' + str(self.__speedtest_time_elapsed)) + else: + logger.warning('could not calculate download speed!') + + time.sleep(self.__configuration.get_speedtest_interval()) + + def write_to_db(self): + return diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..48b8acd --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +requests~=2.28.1 # used by speedtest type +CherryPy~=18.8.0 # used by httpserver plugin \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..e69de29