uplink/bin/uplink

189 lines
7.6 KiB
Text
Raw Normal View History

2021-12-28 23:49:01 +01:00
#!/usr/bin/python3 -d
# Copyright (c) 2020 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
2021-12-28 23:49:01 +01:00
# 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
2021-12-28 23:49:01 +01:00
# 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.
# 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.
2021-12-28 23:49:01 +01:00
import argparse
import calendar
2021-12-28 23:49:01 +01:00
import json
import logging
import logging.handlers
import os
import sys
import time
from uplink.configuration import Configuration
from uplink.uplink import Uplink
2021-12-28 23:49:01 +01:00
__version__ = '0.8.1'
__author__ = 'Johannes Findeisen <you@hanez.org>'
2021-12-28 23:49:01 +01:00
logger = logging.getLogger('uplink')
2021-12-28 23:49:01 +01:00
def parse_args():
parser = argparse.ArgumentParser(
description='uplink is a tool to monitor the link status of AVM FRITZ!Box Cable and DSL '
'based routers.',
epilog='uplink is not some program expecting uplinks to work!',
prog='uplink')
2021-12-28 23:49:01 +01:00
parser.add_argument('configuration_file', metavar='CONFIGFILE',
help='the configuration file to use')
2021-12-28 23:49:01 +01:00
mode = parser.add_mutually_exclusive_group()
mode.add_argument('-c', '--cron', default=False, dest='cron', action='store_true',
help='cron mode executes the script only once without loop (default: false)')
2021-12-28 23:49:01 +01:00
mode.add_argument('-d', '--daemon', default=False, dest='daemon', action='store_true',
help='run as native daemon (default: false)')
parser.add_argument('-k', '--kill', default=False, dest='kill', action='store_true',
help='kill the daemon if it is running (default: false)')
parser.add_argument('-r', '--restart', default=False, dest='restart', action='store_true',
help='restart the daemon if it is running(default: false)')
2021-12-28 23:49:01 +01:00
mode.add_argument('-f', '--foreground', default=False, dest='foreground', action='store_true',
help='run looped in foreground (default: false)')
2021-12-28 23:49:01 +01:00
parser.add_argument('--httpserver', default=False, dest='httpserver', action='store_true',
help='enable the http server for status information and statistics')
2021-12-28 23:49:01 +01:00
parser.add_argument('-i', '--interval', type=int, help='poll interval in seconds. this '
'overrides config file settings (default: 60)')
2021-12-28 23:49:01 +01:00
parser.add_argument('-l', '--logfile', metavar='LOGFILE', help='logfile to use. this '
'overrides config file settings')
2021-12-28 23:49:01 +01:00
parser.add_argument('-s', '--stdout', default=False, dest='stdout', action='store_true',
help='log to stdout')
2021-12-28 23:49:01 +01:00
parser.add_argument('--version', action='version', version='%(prog)s ' + str(__version__))
2021-12-28 23:49:01 +01:00
return parser.parse_args()
def main():
args = parse_args()
try:
with open(args.configuration_file, 'r', encoding='utf-8') as configuration_file:
configuration_data = configuration_file.read()
configuration = Configuration(json.loads(configuration_data))
2021-12-28 23:49:01 +01:00
except Exception as err:
logger.error(str('[uplink] configuration error: {0}'.format(err)))
2021-12-28 23:49:01 +01:00
sys.exit(1)
configuration.set_env_var('_internal_start_date', time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(calendar.timegm(time.gmtime()))))
configuration.set_env_var('_internal_start_timestamp', calendar.timegm(time.gmtime()))
2021-12-28 23:49:01 +01:00
# interval set in args is overriding configuration and default
2021-12-28 23:49:01 +01:00
if args.interval:
configuration.set_interval(args.interval)
2021-12-28 23:49:01 +01:00
if args.logfile:
configuration.set_log_file(args.logfile)
if args.logfile or configuration.get_log_file():
log_file = os.path.expanduser(configuration.get_log_file())
if not os.path.exists(os.path.dirname(log_file)):
os.makedirs(os.path.dirname(log_file))
formatter1 = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s')
handler1 = logging.handlers.RotatingFileHandler(log_file,
maxBytes=configuration.get_log_size(),
backupCount=configuration.get_log_count())
handler1.setFormatter(formatter1)
logger.addHandler(handler1)
if args.stdout:
formatter2 = logging.Formatter('[%(asctime)s] [%(levelname)s] %(message)s')
handler2 = logging.StreamHandler(sys.stdout)
handler2.setFormatter(formatter2)
logger.addHandler(handler2)
# errors will always show up even when no log_level is set!
logger.setLevel(logging.ERROR)
log_level = configuration.get_log_level()
if log_level == "warning":
logger.setLevel(logging.WARNING)
elif log_level == "verbose":
logger.setLevel(logging.INFO)
elif log_level == "debug":
logger.setLevel(logging.DEBUG)
if args.httpserver or configuration.get_httpserver():
configuration.set_httpserver(True)
try:
u = Uplink(configuration.get_pid_file(), configuration)
except Exception as err:
logger.error(str('[uplink] core error! {0}'.format(err)))
sys.exit(1)
2021-12-28 23:49:01 +01:00
if args.cron:
2022-07-31 21:26:18 +02:00
from threading import Thread
for i in range(len(configuration.get_uplinks())):
ct = Thread(target=u.fetch_data, daemon=True, args=(i,))
ct.start()
2021-12-28 23:49:01 +01:00
elif args.daemon:
if args.kill:
u.stop()
elif args.restart:
u.restart()
else:
u.start()
2021-12-28 23:49:01 +01:00
elif args.foreground:
2022-07-31 21:26:18 +02:00
from threading import Thread
if configuration.get_httpserver():
from uplink.httpserver import HTTPServer
s = HTTPServer(configuration)
st = Thread(target=s.run_server, daemon=True)
st.start()
if configuration.get_speedtest():
from uplink.speedtest import Speedtest
se = Speedtest(configuration)
ste = Thread(target=se.run_speedtest, daemon=True)
ste.start()
2021-12-28 23:49:01 +01:00
while True:
for i in range(len(configuration.get_uplinks())):
ft = Thread(target=u.fetch_data, daemon=True, args=(i,))
ft.start()
2021-12-28 23:49:01 +01:00
try:
time.sleep(configuration.get_interval())
except KeyboardInterrupt:
logger.info(str('[uplink] program terminated by user!'))
2021-12-28 23:49:01 +01:00
sys.exit(0)
else:
logger.error('[uplink] no run mode selected; use --cron (-c), --daemon (-d) or '
'--foreground (-f) to run uplink. use --help for more information')
2021-12-28 23:49:01 +01:00
if __name__ == '__main__':
2021-12-28 23:49:01 +01:00
main()