diff --git a/bin/uplink b/bin/uplink index 53bd041..d08c424 100755 --- a/bin/uplink +++ b/bin/uplink @@ -25,8 +25,6 @@ # TODO: Implement a speedtest/ping that will also run regularly but in an individual interval # 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 -# TODO: Maybe make path to pid_file an arg to use /var/run/user/$uid/uplink.pid instead of -# /tmp/uplink.pid or check user id and write it to /var/run or var/run/user/$uid automatically # TODO: make all args consistent and clean... there is some stuff to do! import argparse @@ -113,7 +111,7 @@ def main(): args = parse_args() root_logger = logging.getLogger() - logger.error("TEST") + if args.logfile: logfile = os.path.expanduser(args.logfile) if not os.path.exists(os.path.dirname(logfile)): @@ -143,7 +141,7 @@ def main(): configuration.set_env_var('_start_date', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime( - calendar.timegm(time.gmtime())))) + calendar.timegm(time.gmtime())))) # interval set in args is overriding configuration and default if args.interval: @@ -177,17 +175,17 @@ def main(): if configuration.get_httpserver_framework() == 'bottle': from uplink.server_bottle import Server s = Server(configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() elif configuration.get_httpserver_framework() == 'cherrypy': from uplink.server_cherrypy import Server s = Server(configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() elif configuration.get_httpserver_framework() == 'pyramid': from uplink.server_pyramid import Server s = Server(configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() else: logger.error('[uplink] no http framework configured! ' diff --git a/uplink/csv.py b/uplink/csv.py new file mode 100644 index 0000000..add9185 --- /dev/null +++ b/uplink/csv.py @@ -0,0 +1,32 @@ +# 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(__name__) + + +class Csv: + + def __init__(self, configuration): + self.configuration = configuration + + def write_model_to_csv(self): + return diff --git a/uplink/database.py b/uplink/database.py index 0374cf2..e2be72e 100644 --- a/uplink/database.py +++ b/uplink/database.py @@ -18,13 +18,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. -import calendar import pymysql -import socket -import time from logging import getLogger -from sqlalchemy import create_engine logger = getLogger(__name__) @@ -32,35 +28,57 @@ logger = getLogger(__name__) class Database: def __init__(self, configuration): - self.configuration = configuration - self.date = None - self.time = None - self.status = None - - def write_to_db(self, fc, ip, provider, status): - timestamp = calendar.timegm(time.gmtime()) - local_time = time.localtime(timestamp) - self.date = time.strftime('%Y-%m-%d', local_time) - self.time = time.strftime('%H:%M:%S', local_time) + self.__configuration = configuration + def write_model_to_db(self, model): try: - con = pymysql.connect(host=self.configuration.get_database_host(), - user=self.configuration.get_database_user(), - password=self.configuration.get_database_password(), - database=self.configuration.get_database_name()) + con = pymysql.connect(host=self.__configuration.get_database_host(), + user=self.__configuration.get_database_user(), + password=self.__configuration.get_database_password(), + database=self.__configuration.get_database_name()) - sql = 'INSERT INTO log (timestamp, date, time, uptime, internal_ip, external_ip, external_ipv6, is_linked, ' \ - 'is_connected, str_transmission_rate_up, str_transmission_rate_down, str_max_bit_rate_up, ' \ - 'str_max_bit_rate_down, str_max_linked_bit_rate_up, str_max_linked_bit_rate_down, model_name, ' \ - 'system_version, provider, message, source_host) VALUES (\"' + str(timestamp) + '\",\"' + str(self.date) + '\",\"' + \ - str(self.time) + '\",\"' + str(fc.connection_uptime) + '\",\"' + str(ip) + '\",\"' + \ - str(fc.external_ip) + '\",\"' + str(fc.external_ipv6) + '\",\"' + str(int(fc.is_linked)) + '\",\"' + \ - str(int(fc.is_connected)) + '\",\"' + str(fc.str_transmission_rate[0]) + '\",\"' + \ - str(fc.str_transmission_rate[1]) + '\",\"' + str(fc.str_max_bit_rate[0]) + '\",\"' + \ - str(fc.str_max_bit_rate[1]) + '\",\"' + str(fc.str_max_linked_bit_rate[0]) + '\",\"' + \ - str(fc.str_max_linked_bit_rate[1]) + '\",\"' + str(fc.modelname) + '\",\"' + \ - str(fc.fc.system_version) + '\",\"' + str(provider) + '\",\"' + str(status) + '\",\"' + \ - socket.gethostname() + '\")' + sql = 'INSERT INTO log (' \ + 'timestamp, ' \ + 'date, ' \ + 'time, ' \ + 'uptime, ' \ + 'internal_ip, ' \ + 'external_ip, ' \ + 'external_ipv6, ' \ + 'is_linked, ' \ + 'is_connected, ' \ + 'str_transmission_rate_up, ' \ + 'str_transmission_rate_down, ' \ + 'str_max_bit_rate_up, ' \ + 'str_max_bit_rate_down, ' \ + 'str_max_linked_bit_rate_up, ' \ + 'str_max_linked_bit_rate_down, ' \ + 'model_name, ' \ + 'system_version, ' \ + 'provider, ' \ + 'message, ' \ + 'source_host '\ + ') VALUES (\"' + \ + str(model.get_timestamp()) + '\",\"' + \ + str(model.get_date()) + '\",\"' + \ + str(model.get_time()) + '\",\"' + \ + str(model.get_uptime()) + '\",\"' + \ + str(model.get_internal_ip()) + '\",\"' + \ + str(model.get_external_ip()) + '\",\"' + \ + str(model.get_external_ipv6()) + '\",\"' + \ + str(int(model.get_is_linked())) + '\",\"' + \ + str(int(model.get_is_connected())) + '\",\"' + \ + str(model.get_str_transmission_rate_up()) + '\",\"' + \ + str(model.get_str_transmission_rate_down()) + '\",\"' + \ + str(model.get_str_max_bit_rate_up()) + '\",\"' + \ + str(model.get_str_max_bit_rate_down()) + '\",\"' + \ + str(model.get_str_max_linked_bit_rate_up()) + '\",\"' + \ + str(model.get_str_max_linked_bit_rate_down()) + '\",\"' + \ + str(model.get_model_name()) + '\",\"' + \ + str(model.get_system_version()) + '\",\"' + \ + str(model.get_provider()) + '\",\"' + \ + str(model.get_message()) + '\",\"' + \ + str(model.get_source_host() + '\")') with con.cursor() as cur: cur.execute(sql) diff --git a/uplink/model.py b/uplink/model.py index 2dc12c4..237c37e 100644 --- a/uplink/model.py +++ b/uplink/model.py @@ -26,4 +26,152 @@ logger = getLogger(__name__) class Model: def __init__(self, configuration): - self.configuration = configuration + self.__configuration = configuration + + self.__date = None + self.__external_ip = None + self.__external_ipv6 = None + # no set method for id; it is auto incrementing in the database + self.__id = None + self.__internal_ip = None + self.__is_connected = None + self.__is_linked = None + self.__message = None + self.__model_name = None + self.__provider = None + self.__source_host = None + self.__str_max_bit_rate_down = None + self.__str_max_bit_rate_up = None + self.__str_max_linked_bit_rate_down = None + self.__str_max_linked_bit_rate_up = None + self.__str_transmission_rate_down = None + self.__str_transmission_rate_up = None + self.__system_version = None + self.__time = None + self.__timestamp = None + self.__uptime = None + + # set methods: + def set_date(self, date): + self.__date = date + + def set_external_ip(self, external_ip): + self.__external_ip = external_ip + + def set_external_ipv6(self, external_ipv6): + self.__external_ipv6 = external_ipv6 + + def set_internal_ip(self, internal_ip): + self.__internal_ip = internal_ip + + def set_is_connected(self, is_connected): + self.__is_connected = is_connected + + def set_is_linked(self, is_linked): + self.__is_linked = is_linked + + def set_message(self, message): + self.__message = message + + def set_model_name (self, model_name): + self.__model_name = model_name + + def set_provider(self, provider): + self.__provider = provider + + def set_source_host(self, source_host): + self.__source_host = source_host + + def set_str_max_bit_rate_down(self, str_max_bit_rate_down): + self.__str_max_bit_rate_down = str_max_bit_rate_down + + def set_str_max_bit_rate_up(self, str_max_bit_rate_up): + self.__str_max_bit_rate_up = str_max_bit_rate_up + + def set_str_max_linked_bit_rate_down(self, str_max_linked_bit_rate_down): + self.__str_max_linked_bit_rate_down = str_max_linked_bit_rate_down + + def set_str_max_linked_bit_rate_up(self, str_max_linked_bit_rate_up): + self.__str_max_linked_bit_rate_up = str_max_linked_bit_rate_up + + def set_str_transmission_rate_down(self, str_transmission_rate_down): + self.__str_transmission_rate_down = str_transmission_rate_down + + def set_str_transmission_rate_up(self, str_transmission_rate_up): + self.__str_transmission_rate_up = str_transmission_rate_up + + def set_system_version(self, system_version): + self.__system_version = system_version + + def set_time(self, time): + self.__time = time + + def set_timestamp(self, timestamp): + self.__timestamp = timestamp + + def set_uptime(self, uptime): + self.__uptime = uptime + + # get methods: + def get_date(self): + return self.__date + + def get_external_ip(self): + return self.__external_ip + + def get_external_ipv6(self): + return self.__external_ipv6 + + def get_id(self): + return self.__id + + def get_internal_ip(self): + return self.__internal_ip + + def get_is_connected(self): + return self.__is_connected + + def get_is_linked(self): + return self.__is_linked + + def get_message(self): + return self.__message + + def get_model_name(self): + return self.__model_name + + def get_provider(self): + return self.__provider + + def get_source_host(self): + return self.__source_host + + def get_str_max_bit_rate_down(self): + return self.__str_max_bit_rate_down + + def get_str_max_bit_rate_up(self): + return self.__str_max_bit_rate_up + + def get_str_max_linked_bit_rate_down(self): + return self.__str_max_linked_bit_rate_down + + def get_str_max_linked_bit_rate_up(self): + return self.__str_max_linked_bit_rate_up + + def get_str_transmission_rate_down(self): + return self.__str_transmission_rate_down + + def get_str_transmission_rate_up(self): + return self.__str_transmission_rate_up + + def get_system_version(self): + return self.__system_version + + def get_time(self): + return self.__time + + def get_timestamp(self): + return self.__timestamp + + def get_uptime(self): + return self.__uptime diff --git a/uplink/server_bottle.py b/uplink/server_bottle.py index 1c78618..5a856ec 100644 --- a/uplink/server_bottle.py +++ b/uplink/server_bottle.py @@ -31,17 +31,17 @@ logger = getLogger(__name__) class Server: def __init__(self, configuration): - self.configuration = configuration + self.__configuration = configuration @route('/hello/') def index(self, name): return template('Hello {{name}}!', name=name) @route('/config') - def configuration(self): - return template('
{{config}}
!', config=json.dumps(vars(self.configuration), + def config(self): + return template('
{{config}}
!', config=json.dumps(vars(self.__configuration), sort_keys=True, indent=4)) - def run(self): - run(host=self.configuration.get_httpserver_host(), - port=self.configuration.get_httpserver_port()) + def run_server(self): + run(host=self.__configuration.get_httpserver_host(), + port=self.__configuration.get_httpserver_port()) diff --git a/uplink/server_cherrypy.py b/uplink/server_cherrypy.py index 6a6dd01..bf5f7ce 100644 --- a/uplink/server_cherrypy.py +++ b/uplink/server_cherrypy.py @@ -32,23 +32,23 @@ logger = getLogger(__name__) class Server: def __init__(self, configuration): - self.configuration = configuration + self.__configuration = configuration @cherrypy.expose def index(self): - return "Hello world!" + return 'Hello world!' @cherrypy.expose def config(self): return '
' + \
-               json.dumps(vars(self.configuration), sort_keys=True, indent=4) + \
+               json.dumps(vars(self.__configuration), sort_keys=True, indent=4) + \
                '
' @cherrypy.expose def playground(self): - return "My Playground!" + return 'My Playground!' - def run(self): + def run_server(self): conf = { '/': { # 'tools.sessions.on': True, @@ -73,8 +73,8 @@ class Server: #}) cherrypy.config.update({ 'global': { - 'server.socket_host': self.configuration.get_httpserver_host(), - 'server.socket_port': self.configuration.get_httpserver_port(), + 'server.socket_host': self.__configuration.get_httpserver_host(), + 'server.socket_port': self.__configuration.get_httpserver_port(), 'environment': 'production' } }) diff --git a/uplink/server_pyramid.py b/uplink/server_pyramid.py index dec714a..a87a5e8 100644 --- a/uplink/server_pyramid.py +++ b/uplink/server_pyramid.py @@ -31,16 +31,16 @@ logger = getLogger(__name__) class Server: def __init__(self, configuration): - self.configuration = configuration + self.__configuration = configuration def config(self, request): - return Response(config=json.dumps(vars(self.configuration), sort_keys=True, indent=4)) + return Response(config=json.dumps(vars(self.__configuration), sort_keys=True, indent=4)) - def run(self): + def run_server(self): with Configurator() as config: config.add_route('config', '/') config.add_view(self.config, route_name='config') app = config.make_wsgi_app() - server = make_server(self.configuration.get_httpserver_host(), - self.configuration.get_httpserver_port(), app) + server = make_server(self.__configuration.get_httpserver_host(), + self.__configuration.get_httpserver_port(), app) server.serve_forever() diff --git a/uplink/uplink.py b/uplink/uplink.py index 3b17512..18a47d6 100644 --- a/uplink/uplink.py +++ b/uplink/uplink.py @@ -24,6 +24,7 @@ # be optional too. import calendar +import socket import time from fritzconnection.lib.fritzstatus import FritzStatus @@ -60,13 +61,33 @@ class Uplink(Daemon): else: self.status = 'DOWN' - logger.info(str(uplink['provider'] + ' ' + self.status + ' (ip: ' + - fc.external_ip + ')')) + logger.info(str(uplink['provider'] + ' (uplink IP: ' + fc.external_ip + ') ' + + self.status)) model = Model(self.configuration) + model.set_date(self.date) + model.set_external_ip(fc.external_ip) + model.set_external_ipv6(fc.external_ipv6) + model.set_internal_ip(uplink['ip']) + model.set_is_connected(fc.is_connected) + model.set_is_linked(fc.is_linked) + model.set_message(self.status) + model.set_model_name(fc.modelname) + model.set_provider(uplink['provider']) + model.set_source_host(socket.gethostname()) + model.set_str_max_bit_rate_down(fc.str_max_bit_rate[1]) + model.set_str_max_bit_rate_up(fc.str_max_bit_rate[0]) + model.set_str_max_linked_bit_rate_down(fc.str_max_linked_bit_rate[1]) + model.set_str_max_linked_bit_rate_up(fc.str_max_linked_bit_rate[0]) + model.set_str_transmission_rate_down(fc.str_transmission_rate[1]) + model.set_str_transmission_rate_up (fc.str_transmission_rate[0]) + model.set_system_version(fc.fc.system_version) + model.set_time(self.time) + model.set_timestamp(timestamp) + model.set_uptime(fc.connection_uptime) database = Database(self.configuration) - database.write_to_db(fc, uplink['ip'], uplink['provider'], self.status) + database.write_model_to_db(model) except Exception as err: message = str('error when getting data from ' + uplink['ip'] + ': {0}') @@ -77,17 +98,17 @@ class Uplink(Daemon): if self.configuration.get_httpserver_framework() == 'bottle': from uplink.server_bottle import Server s = Server(self.configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() elif self.configuration.get_httpserver_framework() == 'cherrypy': from uplink.server_cherrypy import Server s = Server(self.configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() elif self.configuration.get_httpserver_framework() == 'pyramid': from uplink.server_pyramid import Server s = Server(self.configuration) - st = Thread(target=s.run, daemon=True) + st = Thread(target=s.run_server, daemon=True) st.start() while True: for i in range(len(self.configuration.get_uplinks())):