Remedy all the pylint-errors

This commit is contained in:
2024-07-03 18:42:19 +02:00
parent 8247be605e
commit 72bf13539d

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
'''Client for the routerstats collection'''
import socket import socket
import logging import logging
@@ -16,46 +17,54 @@ logging.basicConfig(
datefmt='%Y-%m-%d %H:%M:%S') datefmt='%Y-%m-%d %H:%M:%S')
class NotConnected(Exception): class NotConnected(Exception):
logging.error('NotConnected error') '''Raise to make it known that you are not connected'''
pass
class routerstats_client(): class RouterstatsClient():
'''Client itself'''
def __init__(self, host, port, passwd_file): def __init__(self, host, port, passwd_file):
self.host = host self.host = host
self.port = port self.port = port
self.connected = False self.connected = False
self.sock = None
self.passwd_file = passwd_file self.passwd_file = passwd_file
def connect(self): def connect(self):
'''Do connect'''
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try:
self.sock.connect((self.host, self.port)) self.sock.connect((self.host, self.port))
self.sock.settimeout(1) self.sock.settimeout(1)
logging.info('Connected to ' + str(self.host)) logging.info('Connected to %s', self.host)
self.login() self.login()
self.connected = True self.connected = True
except ConnectionRefusedError as error: except ConnectionRefusedError as error:
logging.error('Could not connect to ' + str(self.host) + ':' + str(self.port)) logging.error('Could not connect to %s:%s', self.host, self.port)
raise ConnectionRefusedError(error) raise ConnectionRefusedError from error
except ConnectionError as error: except ConnectionError as error:
logging.error('Could not connect to ' + str(self.host) + ':' + str(self.port) + ': ' + str(error)) logging.error('Could not connect to %s:%s: %s',
self.host,
self.port,
error)
except TimeoutError as error: except TimeoutError as error:
logging.error('Timed out') logging.error('Timed out')
def login(self): def login(self):
#Wait for server to say "hello" '''Do the login routine.
#Reply with password Wait for server to greet us with "hello"
#Wait for "Welcome" reply with the password
wait for "Welcome"
'''
logging.debug('Logging in') logging.debug('Logging in')
try: try:
hello = self.sock.recv(5) hello = self.sock.recv(5)
except TimeoutError: except TimeoutError as exception:
logging.error('Timeout while waiting for Hello') logging.error('Timeout while waiting for Hello')
raise ConnectionError('Timed out waiting for Hello when connecting') raise ConnectionError('Timed out waiting for Hello when connecting') from exception
if not hello == b'Hello': if not hello == b'Hello':
logging.error('No Hello from server: %s', hello) logging.error('No Hello from server: %s', hello)
raise ConnectionError('Server did not greet us with Hello during login') raise ConnectionError('Server did not greet us with Hello during login')
with open(self.passwd_file, 'r') as passwd_file: with open(self.passwd_file, 'r', encoding='utf-8') as passwd_file:
passwd = passwd_file.readline() passwd = passwd_file.readline()
passwd = passwd.rstrip() passwd = passwd.rstrip()
logging.debug('Sending password: %s', passwd) logging.debug('Sending password: %s', passwd)
@@ -66,31 +75,34 @@ class routerstats_client():
logging.error('Not Welcome: %s', response) logging.error('Not Welcome: %s', response)
raise ConnectionError('We are not greeted with Welcome after sending password') raise ConnectionError('We are not greeted with Welcome after sending password')
return True return True
except TimeoutError: except TimeoutError as exception:
raise ConnectionError('Timed out while waiting for server to greet us after sending password') raise ConnectionError(
'Timed out while waiting for server to greet us after sending password') from exception
def send(self, tosend): def send(self, tosend):
'''Send some data'''
if self.connected: if self.connected:
logging.debug('Sending ' + str(tosend)) logging.debug('Sending %s', tosend)
send_bytes = bytes(tosend + "\n", 'utf-8') send_bytes = bytes(tosend + "\n", 'utf-8')
try: try:
self.sock.send(send_bytes) self.sock.send(send_bytes)
except OSError as error: except OSError as error:
logging.error('Cound not send to server: ' + str(error)) logging.error('Cound not send to server: %s', error)
self.connected = False self.connected = False
raise NotConnected raise NotConnected from error
try: try:
self.sock.getpeername() self.sock.getpeername()
except OSError as error: except OSError as error:
logging.error('Could not send to server: ' + str(error)) logging.error('Could not send to server: %s', error)
self.connected = False self.connected = False
raise NotConnected raise NotConnected from error
else: else:
logging.error('Not connected to server') logging.error('Not connected to server')
raise NotConnected('Not connected to server') raise NotConnected('Not connected to server')
def recv(self): def recv(self):
if self.connected != True: '''Receive some data'''
if self.connected is not True:
logging.error('Trying to recv when not connected') logging.error('Trying to recv when not connected')
raise NotConnected raise NotConnected
line = b'' line = b''
@@ -105,7 +117,7 @@ class routerstats_client():
if line.endswith(b'\n'): if line.endswith(b'\n'):
#We're done for now, returning value #We're done for now, returning value
line = line.strip().decode('utf-8') line = line.strip().decode('utf-8')
logging.debug('Received from server: ' + str(line)) logging.debug('Received from server: %s', line)
return line return line
else: else:
blanks += 1 blanks += 1
@@ -115,72 +127,86 @@ class routerstats_client():
logging.debug('Too many blank reads, and still no complete line') logging.debug('Too many blank reads, and still no complete line')
self.connected = False self.connected = False
raise NotConnected raise NotConnected
except TimeoutError:
logging.error('Timeout while fetching data, got: %s' ,line)
break
except OSError as error: except OSError as error:
if str(error) == 'timed out': if str(error) == 'timed out':
#This is expected, as it is how we loop #This is expected, as it is how we loop
break break
logging.error('OSError: ' + str(error)) logging.error('OSError: %s', error)
logging.debug('Got: ' + str(line)) logging.debug('Got: %s', line)
self.connected = False self.connected = False
raise NotConnected(error) raise NotConnected(error) from error
except TimeoutError: return None
logging.error('Timeout while fetching data, got: ' + str(line))
break
def handle_server_msg(received: str): def handle_server_msg(received: str):
'''Do something about something from the server''' '''Do something about something from the server'''
try: try:
timestamp, zone = received.split() timestamp, zone = received.split()
except ValueError: except ValueError:
logging.error('Could not parse ' + str(received) + ' into two distinct values') logging.error('Could not parse %s into two distinct values', received)
return return None
try: try:
timestamp = int(timestamp) timestamp = int(timestamp)
except ValueError: except ValueError:
logging.error('Could not parse ' + str(timestamp) + ' as an int') logging.error('Could not parse %s as an int', timestamp)
return return None
toret = {'timestamp': timestamp, 'net_dnat': 0, 'loc-net': 0} toret = {'timestamp': timestamp, 'net_dnat': 0, 'loc-net': 0}
try: try:
toret[zone] += 1 toret[zone] += 1
except KeyError as error: except KeyError as error:
logging.debug('Ignoring zone: ' + str(error)) logging.debug('Ignoring zone: %s', error)
logging.debug('Parsed to: ' + str(toret)) logging.debug('Parsed to: %s', toret)
return toret return toret
def handle(received, client): def handle(received, client):
'''Do things with whatever came from the server''' '''Do things with whatever came from the server'''
if not received: if not received:
return return None
if received == 'ping': if received == 'ping':
client.send('pong') client.send('pong')
return True return True
elif received is not None: if received is not None:
if received: if received:
return handle_server_msg(received) return handle_server_msg(received)
return None
class UpdateRRD: class UpdateRRD:
'''Handle updates to the rrd-file, since we cannot update more than once every second''' '''Handle updates to the rrd-file, since we cannot update more than once every second'''
def __init__(self, rrdfile): def __init__(self, rrdfile):
self.rrdfile = rrdfile self.rrdfile = rrdfile
if os.path.isfile(rrdfile) != True: if os.path.isfile(rrdfile) is not True:
self.create() self.create()
self.toupdate = {'timestamp': None, 'net_dnat': 0, 'loc-net': 0} self.toupdate = {'timestamp': None, 'net_dnat': 0, 'loc-net': 0}
self.freshdict = self.toupdate.copy() self.freshdict = self.toupdate.copy()
def create(self): def create(self):
rrdtool.create(self.rrdfile, "--start", "1000000000", "--step", "10", "DS:net_dnat:ABSOLUTE:10:0:U", "DS:loc-net:ABSOLUTE:10:0:U", "RRA:AVERAGE:0.5:1:1d", "RRA:AVERAGE:0.5:1:1M") '''Create self.rrdfile'''
logging.debug('Created rrdfile ' + str(self.rrdfile)) rrdtool.create(
self.rrdfile,
"--start",
"1000000000",
"--step",
"10",
"DS:net_dnat:ABSOLUTE:10:0:U",
"DS:loc-net:ABSOLUTE:10:0:U",
"RRA:AVERAGE:0.5:1:1d",
"RRA:AVERAGE:0.5:1:1M")
logging.debug('Created rrdfile %s', self.rrdfile)
def push(self): def push(self):
'''Send data to rrdtool'''
#Make sure we're not doing something stupid.. #Make sure we're not doing something stupid..
info = rrdtool.info(self.rrdfile) info = rrdtool.info(self.rrdfile)
if self.toupdate['timestamp'] is None: if self.toupdate['timestamp'] is None:
return False return False
if info['last_update'] > self.toupdate['timestamp']: if info['last_update'] > self.toupdate['timestamp']:
logging.error('Trying to update when rrdfile is newer than our timestamp. Ignoring line and resetting.') logging.error(
'Trying to update when rrdfile is newer than our timestamp. Ignoring line and resetting.')
self.toupdate = self.freshdict.copy() self.toupdate = self.freshdict.copy()
return False return False
elif info['last_update'] == self.toupdate['timestamp']: if info['last_update'] == self.toupdate['timestamp']:
logging.error('last update and toupdate timestamp are the same, this should not happen') logging.error('last update and toupdate timestamp are the same, this should not happen')
self.toupdate = self.freshdict.copy() self.toupdate = self.freshdict.copy()
return False return False
@@ -202,6 +228,7 @@ class UpdateRRD:
return False return False
def add(self, input_dict): def add(self, input_dict):
'''Add data to be added later'''
if self.toupdate['timestamp'] is None: if self.toupdate['timestamp'] is None:
#Never touched, just overwrite with whatever we got #Never touched, just overwrite with whatever we got
self.toupdate = input_dict self.toupdate = input_dict
@@ -215,15 +242,16 @@ class UpdateRRD:
self.toupdate['loc-net'] += input_dict['loc-net'] self.toupdate['loc-net'] += input_dict['loc-net']
elif input_dict['timestamp'] < self.toupdate['timestamp']: elif input_dict['timestamp'] < self.toupdate['timestamp']:
diff = self.toupdate['timestamp'] - input_dict['timestamp'] diff = self.toupdate['timestamp'] - input_dict['timestamp']
if diff == 1: if diff <= 5:
#Might be because something is a bit slow sometimes? #Might be because something is a bit slow sometimes?
input_dict['timestamp'] = self.toupdate['timestamp'] input_dict['timestamp'] = self.toupdate['timestamp']
else: else:
logging.error('Newly fetched data is older than what we have in the queue already. Passing.') logging.error('Newly fetched data is older than what we have in the queue already. Passing.')
else: else:
logging.error('Not sure what to do here? ' + str(input_dict) + str(self.toupdate)) logging.error('Not sure what to do here? %s: %s', input_dict, self.toupdate)
def loop(client, rrdupdater): def initial_connect(client):
'''Loop here until first connection is made'''
while True: while True:
try: try:
client.connect() client.connect()
@@ -231,6 +259,10 @@ def loop(client, rrdupdater):
except ConnectionRefusedError: except ConnectionRefusedError:
time.sleep(1) time.sleep(1)
def loop(client, rrdupdater):
'''Main loop'''
initial_connect(client)
tries = 0 tries = 0
loops = 0 loops = 0
while True: while True:
@@ -238,7 +270,7 @@ def loop(client, rrdupdater):
retval = handle(client.recv(), client) retval = handle(client.recv(), client)
if retval: if retval:
loops = 0 loops = 0
if retval == True: if retval is True:
pass pass
else: else:
rrdupdater.add(retval) rrdupdater.add(retval)
@@ -248,7 +280,8 @@ def loop(client, rrdupdater):
#Want to wait until at least 5 secs have passed since last actual data fetch.. #Want to wait until at least 5 secs have passed since last actual data fetch..
rrdupdater.push() rrdupdater.push()
if loops >= 60: if loops >= 60:
logging.error('No data in 60 seconds. We expect a ping/pong every 30. Lost connection, probably') logging.error(
'No data in 60 seconds. We expect a ping/pong every 30. Lost connection, probably')
loops = 0 loops = 0
raise NotConnected raise NotConnected
except NotConnected: except NotConnected:
@@ -256,18 +289,18 @@ def loop(client, rrdupdater):
client.connect() client.connect()
tries = 0 tries = 0
except ConnectionRefusedError as error: except ConnectionRefusedError as error:
logging.debug(str(error)) logging.debug('%s', error)
tries += 1 tries += 1
if tries >= 5: tries = min(tries, 5)
tries = 5
time.sleep(tries) time.sleep(tries)
except ConnectionRefusedError as error: except ConnectionRefusedError as error:
logging.debug(str(error)) logging.debug('%s', error)
time.sleep(1) time.sleep(1)
except KeyboardInterrupt: except KeyboardInterrupt:
break break
def main(): def main():
'''Main is main'''
config_section = 'client' config_section = 'client'
config = configparser.ConfigParser() config = configparser.ConfigParser()
@@ -276,12 +309,12 @@ def main():
parser.add_argument('-c', '--config', help='config file to load') parser.add_argument('-c', '--config', help='config file to load')
parser.add_argument('-d', '--debug', action='store_true', help='enable debug') parser.add_argument('-d', '--debug', action='store_true', help='enable debug')
args, remaining_args = parser.parse_known_args() args, _ = parser.parse_known_args()
if args.debug: if args.debug:
logging.root.setLevel(logging.DEBUG) logging.root.setLevel(logging.DEBUG)
logging.debug('Starting as PID ' + str(os.getpid())) logging.debug('Starting as PID %s', os.getpid())
found = False found = False
if args.config: if args.config:
@@ -304,10 +337,31 @@ def main():
sys.exit(0) sys.exit(0)
parser.add_argument('-r', '--host', dest='host', help='ip/hostname to connect to', default=config[config_section]['host']) parser.add_argument(
parser.add_argument('-p', '--port', dest='port', type=int, help='port to connect to', default=config[config_section]['port']) '-r',
parser.add_argument('-v', '--vardir', dest='vardir', help='directory for storing rrd file', default=config[config_section]['var_dir']) '--host',
parser.add_argument('-w', '--pwdfile', dest='passwd_file', help='password file', default=config[config_section]['passwd_file']) dest='host',
help='ip/hostname to connect to',
default=config[config_section]['host'])
parser.add_argument(
'-p',
'--port',
dest='port',
type=int,
help='port to connect to',
default=config[config_section]['port'])
parser.add_argument(
'-v',
'--vardir',
dest='vardir',
help='directory for storing rrd file',
default=config[config_section]['var_dir'])
parser.add_argument(
'-w',
'--pwdfile',
dest='passwd_file',
help='password file',
default=config[config_section]['passwd_file'])
args = parser.parse_args() args = parser.parse_args()
logging.debug(args) logging.debug(args)
@@ -321,7 +375,7 @@ def main():
logging.error('Cannot find var dir %s', args.vardir) logging.error('Cannot find var dir %s', args.vardir)
rrdupdater = UpdateRRD(args.vardir + '/routerstats.rrd') rrdupdater = UpdateRRD(args.vardir + '/routerstats.rrd')
client = routerstats_client(args.host, args.port, args.passwd_file) client = RouterstatsClient(args.host, args.port, args.passwd_file)
loop(client, rrdupdater) loop(client, rrdupdater)
if __name__ == '__main__': if __name__ == '__main__':