Aktualisierung auf Python 3 und einige kleine Verbesserungen

master
Thomas Hooge 2023-12-06 07:51:04 +01:00
parent 88cfca048f
commit 1844652e4d
3 changed files with 87 additions and 41 deletions

2
README
View File

@ -1,6 +1,6 @@
Achtung, Verwendung aller Programme auf eigene Gefahr! Achtung, Verwendung aller Programme auf eigene Gefahr!
Vor Inbetriebnahme ist jedes Script daraufhin zu überprüfen, Vor Inbetriebnahme ist jedes Script daraufhin zu überprüfen,
ob noch Konfigurationseinstellungen vorgenommen werder müssen. ob noch Konfigurationseinstellungen vorgenommen werden müssen.
Z.B. muß bei ffgate-check die IP-Aresse des anzupingenden Hosts Z.B. muß bei ffgate-check die IP-Aresse des anzupingenden Hosts
eingetragen werden. eingetragen werden.

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
@ -39,6 +39,8 @@ Version Datum Änderung(en) von
0.2 2016-08-30 Automatisierung Land des Exit-VPNs tho 0.2 2016-08-30 Automatisierung Land des Exit-VPNs tho
0.3 2016-12-04 DHCPD-Leases integrieren zur Anzeige der Clientanz. tho 0.3 2016-12-04 DHCPD-Leases integrieren zur Anzeige der Clientanz. tho
0.4 2017-02-10 Communityunabhängig durch sitecode als Einstellung tho 0.4 2017-02-10 Communityunabhängig durch sitecode als Einstellung tho
0.5 2022-10-05 Umbau auf python3 für Einsatz unter Debian 11 tho
0.6 2023-01-02 -m bei batctl deprecated: durch meshif ersetzt tho
""" """
@ -49,7 +51,8 @@ import platform
import getopt import getopt
import signal import signal
import daemon import daemon
from collections import defaultdict, Mapping from collections import defaultdict
from collections.abc import Mapping
import json import json
import subprocess import subprocess
import socket import socket
@ -58,6 +61,13 @@ import time
import logging import logging
import re import re
import datetime import datetime
import functools
__author__ = "Thomas Hooge"
__copyright__ = "Public Domain"
__version__ = "0.6"
__email__ = "thomas@hoogi.de"
__status__ = "Development"
cfg = { cfg = {
'logfile': '/var/log/alfred-announced.log', 'logfile': '/var/log/alfred-announced.log',
@ -107,7 +117,7 @@ def fn_node_net_mesh_ifaces():
# Die Stelle mit "bat0" müßte dynamisch aufgrund der Interfaces # Die Stelle mit "bat0" müßte dynamisch aufgrund der Interfaces
# zusammengebaut werden # zusammengebaut werden
return [open('/sys/class/net/' + iface + '/address').read().strip() return [open('/sys/class/net/' + iface + '/address').read().strip()
for iface in map(lambda line: line.split(':')[0], call(['batctl', '-m', cfg['interface'], 'if']))] for iface in map(lambda line: line.split(':')[0], call(['batctl', 'meshif', cfg['interface'], 'if']))]
def fn_exitvpn_provider(): def fn_exitvpn_provider():
""" """
@ -151,7 +161,8 @@ def fn_fastd_enabled():
- prüfe, ob das Script tatsächlich existiert - prüfe, ob das Script tatsächlich existiert
""" """
runlevel = int(call(['runlevel'])[0].split(' ')[1]) runlevel = int(call(['runlevel'])[0].split(' ')[1])
fname = glob.glob("/etc/rc%d.d/S??fastd" % runlevel) #fname = glob.glob("/etc/rc%d.d/S??fastd" % runlevel)
fname = glob.glob("/etc/rc{:02d}.d/S??fastd".format(runlevel))
if not fname: if not fname:
return False return False
return os.path.isfile(fname[0]) return os.path.isfile(fname[0])
@ -168,7 +179,10 @@ def fn_firmware_base():
return call(['lsb_release','-is'])[0] return call(['lsb_release','-is'])[0]
def fn_firmware_release(): def fn_firmware_release():
return call(['lsb_release','-rs'])[0] if fn_firmware_base() == 'Debian':
return call(['cat','/etc/debian_version'])[0]
else:
return call(['lsb_release','-rs'])[0]
def fn_idletime(): def fn_idletime():
return float(open('/proc/uptime').read().split(' ')[1]) return float(open('/proc/uptime').read().split(' ')[1])
@ -227,12 +241,14 @@ def fn_fastd_peers():
data = json.loads(client.makefile('r').read()) data = json.loads(client.makefile('r').read())
client.close() client.close()
# 2. Gateways ermitteln (MACs) # 2. Gateways ermitteln (MACs)
with open('/sys/kernel/debug/batman_adv/{0}/gateways'.format(cfg['interface'])) as f: # deprecated
lines = f.readlines() #with open('/sys/kernel/debug/batman_adv/{0}/gateways'.format(cfg['interface'])) as f:
# lines = f.readlines()
lines = call(['batctl', 'meshif', cfg['interface'], 'gwl'])
gw_macs = set([gw[3:20] for gw in lines[1:]]) gw_macs = set([gw[3:20] for gw in lines[1:]])
# 3. Ergebnis ermitteln # 3. Ergebnis ermitteln
npeers = 0 npeers = 0
for peer in data['peers'].itervalues(): for peer in data['peers'].values():
if peer['connection']: if peer['connection']:
if not set(peer['connection']['mac_addresses']) & gw_macs: if not set(peer['connection']['mac_addresses']) & gw_macs:
npeers += 1 npeers += 1
@ -285,21 +301,21 @@ item = {
#items_by_interval = defaultdict(list) #items_by_interval = defaultdict(list)
#for k, v in item.iteritems(): #for k, v in item.iteritems():
# items_by_interval[v['interval']].append(k) # items_by_interval[v['interval']].append(k)
#print items_by_interval #print(items_by_interval)
#for i in items_by_interval: #for i in items_by_interval:
# print i # print(i)
# Datenstruktur zum Übertragen an Alfred. # Datenstruktur zum Übertragen an Alfred.
# Wir nehmen die optimale Variante, ggf. ist das *nicht* # Wir nehmen die optimale Variante, ggf. ist das *nicht*
# JSON # JSON
def dot_to_json(a): def dot_to_json(a):
output = {} output = {}
for key, value in a.iteritems(): for key, value in a.items():
path = key.split('.') path = key.split('.')
if path[0] == 'json': if path[0] == 'json':
path = path[1:] path = path[1:]
target = reduce(lambda d, k: d.setdefault(k, {}), path[:-1], output) target = functools.reduce(lambda d, k: d.setdefault(k, {}), path[:-1], output)
target[path[-1]] = value target[path[-1]] = value
return output return output
@ -327,12 +343,12 @@ def set_loglevel(nr):
return level return level
def usage(): def usage():
print "Alfred Announce Daemon for Gateways" print("Alfred Announce Daemon for Gateways")
print "Version %s" % __version__ print("Version {}".format(__version__))
print print()
print "Optionen" print("Optionen")
print " -d Programm als Daemon laufen lassen" print(" -d Programm als Daemon laufen lassen")
print print()
if __name__ == "__main__": if __name__ == "__main__":
@ -342,8 +358,8 @@ if __name__ == "__main__":
# Kommandozeilenoptionen verarbeiten # Kommandozeilenoptionen verarbeiten
try: try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "dh", ["daemon", "help"]) opts, args = getopt.gnu_getopt(sys.argv[1:], "dh", ["daemon", "help"])
except getopt.GetoptError, err: except getopt.GetoptError as err:
print str(err) print(str(err))
sys.exit(2) sys.exit(2)
for opt, arg in opts: for opt, arg in opts:
if opt in ("-h", "--help"): if opt in ("-h", "--help"):
@ -363,13 +379,13 @@ if __name__ == "__main__":
loglevel = set_loglevel(cfg['loglevel']) loglevel = set_loglevel(cfg['loglevel'])
if loglevel: if loglevel:
log.setLevel(loglevel) log.setLevel(loglevel)
log.info("%s started on %s" % (sys.argv[0], socket.gethostname())) log.info("{} started on {}".format(sys.argv[0], socket.gethostname()))
else: else:
log.disabled = True log.disabled = True
# Zugeordnete Funktionen je Item ausführen # Zugeordnete Funktionen je Item ausführen
result = {} result = {}
for k, v in item.iteritems(): for k, v in item.items():
result[k] = v['exec']() result[k] = v['exec']()
# Daten für Alfred aufbereiten, wir verwenden gzip # Daten für Alfred aufbereiten, wir verwenden gzip
@ -383,28 +399,28 @@ if __name__ == "__main__":
statics = {} statics = {}
except ValueError: except ValueError:
statics = {} statics = {}
print "Syntax error in statics file, import failed" print("Syntax error in statics file, import failed")
merge_dict(data, statics) merge_dict(data, statics)
# Aufteilen in die jew. Datentypen # Aufteilen in die jew. Datentypen
nodeinfo = data['node'] nodeinfo = data['node']
statistics = data['statistics'] statistics = data['statistics']
cnodeinfo = zlib.compress(json.dumps(nodeinfo)) cnodeinfo = zlib.compress(bytes(json.dumps(nodeinfo), 'UTF-8'))
cstatistics = zlib.compress(json.dumps(statistics)) cstatistics = zlib.compress(bytes(json.dumps(statistics), 'UTF-8'))
# Knoteninfos übertragen # Knoteninfos übertragen
alfred = subprocess.Popen(['alfred', '-s', '158'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) alfred = subprocess.Popen(['alfred', '-s', '158'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
streamdata = alfred.communicate(cnodeinfo)[0] streamdata = alfred.communicate(cnodeinfo)[0]
if alfred.returncode != 0: if alfred.returncode != 0:
print "Communication error with alfred: %s" % streamdata print("Communication error with alfred: {}".format(streamdata))
# Statistik übertragen # Statistik übertragen
alfred = subprocess.Popen(['alfred', '-s', '159'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) alfred = subprocess.Popen(['alfred', '-s', '159'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
streamdata = alfred.communicate(cstatistics)[0] streamdata = alfred.communicate(cstatistics)[0]
if alfred.returncode != 0: if alfred.returncode != 0:
print "Communication error with alfred: %s" % streamdata print("Communication error with alfred: {}".format(streamdata))
# Zeitmessung beenden # Zeitmessung beenden
tn = time.time() tn = time.time()
log.info(u"Benötigte Zeit: %.2f Minuten" % ((tn-t0)/60)) log.info("Benötigte Zeit: {:.2f} Minuten" .format((tn-t0)/60))

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
@ -6,29 +6,55 @@ Informationen aus dem fastd-Socket anzeigen.
Voraussetzung ist natürlich, daß dieser über die fastd-Konfiguration Voraussetzung ist natürlich, daß dieser über die fastd-Konfiguration
eingeschaltet ist. eingeschaltet ist.
Programm von Freifunk Pinneberg / Havelock Programm von Freifunk Pinneberg / Havelock
TODO Mehr automatisieren
- pidof fastd liefert Liste mit laufenden Prozessen (Trennung mit Leerzeichen)
- /proc/<pid>/cmdline liefert Kommando mit Konfigurationsdatei
- dann Konfigurationsdatei auswerten
Änderungsprotokoll
==================
Version Datum Änderung(en) von
-------- ----------- ------------------------------------------------------ ----
0.1 2015-09-27 Änderungsprotokoll eingebaut tho
0.2 2023-01-08 Umstellung auf Python 3 tho
0.3 2023-12-06 Zugriff auf debugfs für GW-Interfaces entfernt tho
""" """
import os import os
import sys import sys
import socket import socket
import json import json
import subprocess
__author__ = "Thomas Hooge"
__copyright__ = "Public Domain"
__version__ = "0.3"
__email__ = "thomas@hoogi.de"
__status__ = "Development"
def call(cmdnargs):
output = subprocess.check_output(cmdnargs)
lines = [line.decode("utf-8") for line in output.splitlines()]
return lines
def get_fastd_data(sockfile): def get_fastd_data(sockfile):
# fastd-Socket auslesen, liefert ein JSON-Objekt # fastd-Socket auslesen, liefert ein JSON-Objekt
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
try: try:
client.connect(sockfile) client.connect(sockfile)
except socket.error, msg: except socket.error as msg:
print >>sys.stderr, msg print(msg, file=sys.stderr)
sys.exit(1) sys.exit(1)
data = json.loads(client.makefile('r').read()) data = json.loads(client.makefile('r').read())
client.close() client.close()
return data return data
def get_gate_macs(): def get_gate_macs():
# Ermitteln der (sichtbaten) Gateways # Ermitteln der (sichtbaren) Gateways
with open('/sys/kernel/debug/batman_adv/bat0/gateways') as f: lines = call(['batctl', 'meshif', 'bat0', 'gwl'])
lines = f.readlines()
return set([gw[3:20] for gw in lines[1:]]) return set([gw[3:20] for gw in lines[1:]])
def main(): def main():
@ -36,15 +62,19 @@ def main():
gw_macs = get_gate_macs() gw_macs = get_gate_macs()
npeers = 0 npeers = 0
ngates = 0 ngates = 0
for key, peer in data['peers'].iteritems(): for key, peer in data['peers'].items():
if peer['connection']: if peer['connection']:
if set(peer['connection']['mac_addresses']) & gw_macs: if set(peer['connection']['mac_addresses']) & gw_macs:
print "Gate %s (%s) connected as %s..." % (peer['name'], peer['connection']['mac_addresses'][0], key[:16]) print("Gate %s (%s) connected as %s..." % (peer['name'], peer['connection']['mac_addresses'][0], key[:16]))
ngates += 1 ngates += 1
else: else:
print "Peer %s (%s) connected as %s..." % (peer['name'], peer['connection']['mac_addresses'][0], key[:16]) try:
peer_mac = peer['connection']['mac_addresses'][0]
except:
peer_mac = '*no mac*'
print("Peer %s (%s) connected as %s..." % (peer['name'], peer_mac, key[:16]))
npeers += 1 npeers += 1
print "%d peers total, %d gateways and %d peers currently connected" % (len(data['peers']), ngates, npeers) print("%d peers total, %d gateways and %d peers currently connected" % (len(data['peers']), ngates, npeers))
if __name__ == '__main__': if __name__ == '__main__':
main() main()