diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..746b305 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +PRIMARY AUTHORS are and/or have been (alphabetic order): + +* Findeisen, Johannes + Main Developer since the first code line. + github.com profile: + openhub.net profile: + Homepage: \ No newline at end of file diff --git a/bin/uplink b/bin/uplink index 6ade893..316d964 100755 --- a/bin/uplink +++ b/bin/uplink @@ -21,8 +21,9 @@ # OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # TODO: CHECK ALL ERROR HANDLING!!! +# TODO: Refactor all logging and make it clean and consistent. # TODO: become more verbose in each log level and log only to error when it really -# is an error else log to info and even add debug messages in DEBUG level +# is an error else log to info and even add debug messages in DEBUG level. import argparse import calendar @@ -36,10 +37,10 @@ import time from uplink.configuration import Configuration from uplink.uplink import Uplink -__version__ = '0.8.0' +__version__ = '0.8.1' __author__ = 'Johannes Findeisen ' -logger = logging.getLogger(__name__) +logger = logging.getLogger('uplink') def parse_args(): @@ -88,14 +89,12 @@ def parse_args(): def main(): args = parse_args() - root_logger = logging.getLogger() - try: with open(args.configuration_file, 'r', encoding='utf-8') as configuration_file: configuration_data = configuration_file.read() configuration = Configuration(json.loads(configuration_data)) except Exception as err: - logger.error(str('[uplink] configuration error! {0}'.format(err))) + logger.error(str('[uplink] configuration error: {0}'.format(err))) sys.exit(1) configuration.set_env_var('_internal_start_date', time.strftime('%Y-%m-%d %H:%M:%S', @@ -119,23 +118,23 @@ def main(): maxBytes=configuration.get_log_size(), backupCount=configuration.get_log_count()) handler1.setFormatter(formatter1) - root_logger.addHandler(handler1) + logger.addHandler(handler1) if args.stdout: formatter2 = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s') handler2 = logging.StreamHandler(sys.stdout) handler2.setFormatter(formatter2) - root_logger.addHandler(handler2) + logger.addHandler(handler2) # errors will always show up even when no log_level is set! - root_logger.setLevel(logging.ERROR) + logger.setLevel(logging.ERROR) log_level = configuration.get_log_level() if log_level == "warning": - root_logger.setLevel(logging.WARNING) + logger.setLevel(logging.WARNING) elif log_level == "verbose": - root_logger.setLevel(logging.INFO) + logger.setLevel(logging.INFO) elif log_level == "debug": - root_logger.setLevel(logging.DEBUG) + logger.setLevel(logging.DEBUG) if args.httpserver or configuration.get_httpserver(): configuration.set_httpserver(True) @@ -182,7 +181,7 @@ def main(): logger.info(str('[uplink] program terminated by user!')) sys.exit(0) else: - logger.error('uplink: no run mode selected; use --cron (-c), --daemon (-d) or ' + logger.error('[uplink] no run mode selected; use --cron (-c), --daemon (-d) or ' '--foreground (-f) to run uplink. use --help for more information') diff --git a/uplink/configuration.py b/uplink/configuration.py index c136790..16d3b71 100644 --- a/uplink/configuration.py +++ b/uplink/configuration.py @@ -18,9 +18,12 @@ # 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 re +import socket + from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Configuration: @@ -45,7 +48,7 @@ class Configuration: self.__log_level = None self.__log_size = 0 self.__notification_gammu = False - self.__notification_gammu_configuration = None + self.__notification_gammu_configuration_file = None self.__notification_gammu_receiver = None self.__notification_gammu_repeat = 30 self.__pid_file = '/tmp/uplink.pid' @@ -102,12 +105,12 @@ class Configuration: if 'notification_gammu' in self.__configuration: self.__notification_gammu = self.__configuration['notification_gammu'] - if 'notification_gammu_configuration' in self.__configuration: - self.__notification_gammu_configuration = \ - self.__configuration['notification_gammu_configuration'] - elif self.__notification_gammu_configuration is None and \ + if 'notification_gammu_configuration_file' in self.__configuration: + self.__notification_gammu_configuration_file = \ + self.__configuration['notification_gammu_configuration_file'] + elif self.__notification_gammu_configuration_file is None and \ 'notification_gammu' in self.__configuration: - raise Exception('notification_gammu_configuration required!') + raise Exception('notification_gammu_configuration_file required!') if 'notification_gammu_receiver' in self.__configuration: self.__notification_gammu_receiver = \ @@ -136,6 +139,26 @@ class Configuration: if 'uplinks' in self.__configuration: self.__uplinks = self.__configuration['uplinks'] + for uplink in self.__uplinks: + if 'identifier' not in uplink: + raise Exception('missing at least one identifier in an uplink!') + if bool(re.match('^[a-z]+$', uplink['identifier'])) is False: + raise Exception('uplink identifier ' + uplink['identifier'] + + ' must only contain lowercase letters!') + + if 'ip' not in uplink: + raise Exception('missing ip for identifier ' + uplink['identifier'] + '!') + try: + socket.inet_aton(uplink['ip']) + except Exception as err: + raise Exception('invalid ip for identifier ' + uplink['identifier'] + '!') + + if 'password' not in uplink: + raise Exception('missing password for identifier ' + uplink['identifier'] + '!') + + if 'provider' not in uplink: + uplink['provider'] = 'Not configured' + if self.__uplinks is None: raise Exception('uplinks required!') @@ -191,7 +214,7 @@ class Configuration: def get_notification_gammu(self): return self.__notification_gammu - def get_notification_gammu_configuration(self): + def get_notification_gammu_configuration_file(self): return self.__notification_gammu_configuration def get_notification_gammu_receiver(self): diff --git a/uplink/csv.py b/uplink/csv.py index 5db35ee..d57374b 100644 --- a/uplink/csv.py +++ b/uplink/csv.py @@ -20,7 +20,7 @@ from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class CSV: diff --git a/uplink/daemon.py b/uplink/daemon.py index 1f1f689..6523d3e 100644 --- a/uplink/daemon.py +++ b/uplink/daemon.py @@ -26,7 +26,7 @@ import time from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Daemon: diff --git a/uplink/database.py b/uplink/database.py index 113ea86..c26e802 100644 --- a/uplink/database.py +++ b/uplink/database.py @@ -22,7 +22,7 @@ import pymysql from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Database: diff --git a/uplink/httpserver.py b/uplink/httpserver.py index 8e19c6f..e042360 100644 --- a/uplink/httpserver.py +++ b/uplink/httpserver.py @@ -26,7 +26,7 @@ import json from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class HTTPServer: diff --git a/uplink/model.py b/uplink/model.py index 00901e4..a96bee2 100644 --- a/uplink/model.py +++ b/uplink/model.py @@ -20,7 +20,7 @@ from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Model: diff --git a/uplink/notification.py b/uplink/notification.py index 808dcde..e2f3217 100644 --- a/uplink/notification.py +++ b/uplink/notification.py @@ -22,7 +22,7 @@ from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Notification: @@ -31,7 +31,7 @@ class Notification: self.__configuration = configuration #self.__state_machine = gammu.StateMachine() #self.__state_machine.ReadConfig( - # self.__configuration.get_notification_gammu_configuration()) + # self.__configuration.get_notification_gammu_configuration_file()) def send(self, status): #message = { diff --git a/uplink/speedtest.py b/uplink/speedtest.py index 39f3a5c..ea919d1 100644 --- a/uplink/speedtest.py +++ b/uplink/speedtest.py @@ -24,7 +24,7 @@ import time from logging import getLogger -logger = getLogger(__name__) +logger = getLogger('uplink') class Speedtest: @@ -32,9 +32,9 @@ class Speedtest: def __init__(self, configuration): self.__configuration = configuration - self.speedtest_maximum_speed = None - self.speedtest_average_speed = None - self.speedtest_time_elapsed = None + self.__speedtest_maximum_speed = None + self.__speedtest_average_speed = None + self.__speedtest_time_elapsed = None def run_speedtest(self): while True: @@ -64,19 +64,22 @@ class Speedtest: total_chunks += 1 total_mbps += mbps - self.speedtest_maximum_speed = maximum_speed - self.__configuration.set_env_var('_speedtest_maximum_speed_megabyte_per_second', - str(round(self.speedtest_maximum_speed))) - - self.speedtest_average_speed = total_mbps / total_chunks + self.__speedtest_average_speed = total_mbps / total_chunks self.__configuration.set_env_var('_speedtest_average_speed_megabyte_per_second', - str(round(self.speedtest_average_speed))) + str(round(self.__speedtest_average_speed))) - self.speedtest_time_elapsed = time.perf_counter() - start + self.__speedtest_maximum_speed = maximum_speed + self.__configuration.set_env_var('_speedtest_maximum_speed_megabyte_per_second', + str(round(self.__speedtest_maximum_speed))) + + self.__speedtest_time_elapsed = time.perf_counter() - start self.__configuration.set_env_var('_speedtest_time_elapsed', - str(self.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!") + logger.warning('could not calculate download speed!') time.sleep(self.__configuration.get_speedtest_interval()) diff --git a/uplink/uplink.py b/uplink/uplink.py index 861bc07..4847454 100644 --- a/uplink/uplink.py +++ b/uplink/uplink.py @@ -23,6 +23,7 @@ # be optional too. Also reinvent SQLite as database backend. import calendar +import logging import socket import time @@ -33,7 +34,7 @@ from uplink.daemon import Daemon from uplink.database import Database from uplink.model import Model -logger = getLogger(__name__) +logger = getLogger('uplink') class Uplink(Daemon): @@ -86,7 +87,7 @@ class Uplink(Daemon): self.__configuration.set_env_var('_uplink_' + uplink['identifier'] + '_status', 'UP') - status = 'UP' + status = 'up' else: fail_count = self.__configuration.get_env_var('_uplink_' + uplink['identifier'] + '_fail_count') @@ -111,7 +112,7 @@ class Uplink(Daemon): self.__configuration.set_env_var('_uplink_' + uplink['identifier'] + '_status', 'DOWN') - status = 'DOWN' + status = 'down' if self.__configuration.get_notification_gammu() is True: notification_gammu_repeat = self.__configuration.get_notification_gammu_repeat() @@ -126,8 +127,7 @@ class Uplink(Daemon): notification = Notification(self.__configuration) notification.send('[' + uplink['provider'] + '] ' + status) - logger.info(str(uplink['provider'] + ' (IP: ' + fritz_connection.external_ip + ') ' + - status)) + logger.info(str(uplink['identifier'] + ': ' + status)) model = Model(self.__configuration) model.set_date(date_formatted) @@ -155,21 +155,21 @@ class Uplink(Daemon): database.write_log_to_db(model) except Exception as err: - message = str('error when getting data from ' + uplink['ip'] + ': {0}') + message = str('error when getting data from ' + uplink['ip'] + '') logger.error(str(message.format(err))) def run(self): if self.__configuration.get_http_server(): from uplink.httpserver import HTTPServer - s = HTTPServer(self.__configuration) - st = Thread(target=s.run_server, daemon=True) - st.start() + hs = HTTPServer(self.__configuration) + hst = Thread(target=hs.run_server, daemon=True) + hst.start() if self.__configuration.get_speedtest(): from uplink.speedtest import Speedtest - se = Speedtest(self.__configuration) - ste = Thread(target=se.run_speedtest, daemon=True) - ste.start() + st = Speedtest(self.__configuration) + stt = Thread(target=st.run_speedtest, daemon=True) + stt.start() while True: for i in range(len(self.__configuration.get_uplinks())):