From 44c92ff65f35a8ed73cd79b4f29e4fd0afa998f3 Mon Sep 17 00:00:00 2001 From: Daniel Ehlers Date: Tue, 12 Nov 2013 00:28:11 +0100 Subject: [PATCH] Refactor batctl calls into python class. This drastically reduces the logic implement in mkmap.sh and also supports multiple batman mesh interfaces. --- bat2nodes.py | 22 +++++++++++------- batman.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mkmap.sh | 12 +--------- nodedb.py | 16 ++++--------- 4 files changed, 85 insertions(+), 30 deletions(-) create mode 100755 batman.py diff --git a/bat2nodes.py b/bat2nodes.py index ab4d5fd..d68be00 100755 --- a/bat2nodes.py +++ b/bat2nodes.py @@ -4,6 +4,7 @@ import json import fileinput import argparse +from batman import batman from nodedb import NodeDB from d3mapbuilder import D3MapBuilder @@ -23,25 +24,30 @@ parser.add_argument('-a', '--aliases', action='append', metavar='FILE') -parser.add_argument('-g', '--gateway', action='append', - help='MAC of a gateway') - -parser.add_argument('batmanjson', help='output of batman vd json') +parser.add_argument('-m', '--mesh', action='append', + help='batman mesh interface') args = parser.parse_args() options = vars(args) db = NodeDB() -db.import_batman(list(fileinput.input(options['batmanjson']))) +if options['mesh']: + for mesh_interface in options['mesh']: + bm = batman(mesh_interface) + db.parse_vis_data(bm.vis_data()) + for gw in bm.gateway_list(): + db.mark_gateways(gw.mac) +else: + bm = batman() + db.parse_vis_data(bm.vis_data()) + for gw in bm.gateway_list(): + db.mark_gateways([gw['mac']]) if options['aliases']: for aliases in options['aliases']: db.import_aliases(json.load(open(aliases))) -if options['gateway']: - db.mark_gateways(options['gateway']) - m = D3MapBuilder(db) print(m.build()) diff --git a/batman.py b/batman.py new file mode 100755 index 0000000..5a19016 --- /dev/null +++ b/batman.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +import subprocess +import json +import re + +class batman: + """ Bindings for B.A.T.M.A.N. advanced batctl tool + """ + def __init__(self, mesh_interface = "bat0"): + self.mesh_interface = mesh_interface + + def vis_data(self): + """ Parse "batctl -m vd json -n" into an array of dictionaries. + """ + output = subprocess.check_output(["batctl","-m",self.mesh_interface,"vd","json","-n"]) + lines = output.splitlines() + vd = [] + for line in lines: + try: + utf8_line = line.decode("utf-8") + vd.append(json.loads(utf8_line)) + except e: + pass + return vd + + def gateway_list(self): + """ Parse "batctl -m gwl -n" into an array of dictionaries. + """ + output = subprocess.check_output(["batctl","-m",self.mesh_interface,"gwl","-n"]) + output_utf8 = output.decode("utf-8") + # TODO Parse information + lines = output_utf8.splitlines() + own_mac = re.match(r"^.*MainIF/MAC: [^/]+/([0-9a-f:]+).*$",lines[0]).group(1) + # Remove header line + del lines[0] + # Fill gateway list + gw = [] + gw_mode = self.gateway_mode() + if gw_mode['mode'] == 'server': + gw.append({'mac': own_mac, 'bandwidth': gw_mode['bandwidth']}) + for line in lines: + gw_line = line.split() + # When in client gateway mode maybe gw_line[0] is not the right. + gw.append({'mac':gw_line[0], 'bandwidth': gw_line[-1]}) + return gw + + def gateway_mode(self): + """ Parse "batctl -m gw" + """ + output = subprocess.check_output(["batctl","-m",self.mesh_interface,"gw"]) + elements = output.decode("utf-8").split() + mode = elements[0] + if mode == "server": + return {'mode': 'server', 'bandwidth': elements[3]} + else: + return {'mode': mode} + +if __name__ == "__main__": + bc = batman() + vd = bc.vis_data() + gw = bc.gateway_list() + for x in vd: + print(x) + print(gw) + print(bc.gateway_mode()) diff --git a/mkmap.sh b/mkmap.sh index 13ec9ec..e82a1c2 100755 --- a/mkmap.sh +++ b/mkmap.sh @@ -7,20 +7,10 @@ DEST=$1 [ "$DEST" ] || exit 1 - -GWL=`batctl gwl -n` - -SELF=`echo "$GWL" | head -n 1 | sed -r -e 's@^.*MainIF/MAC: [^/]+/([0-9a-f:]+).*$@\1@'` -GWS=`(echo "$GWL" | tail -n +2 | grep -v '^No' | sed 's/=>//' | awk '{ print $1 }') | while read a; do echo -n "-g $a "; done` - -if [ `cat /sys/class/net/bat0/mesh/gw_mode` = server ]; then - GWS="$GWS -g $SELF" -fi - "$(dirname "$0")"/ffhlwiki.py http://freifunk.metameute.de/wiki/Knoten > "$(dirname "$0")"/aliases_hl.json "$(dirname "$0")"/ffhlwiki.py http://freifunk.metameute.de/wiki/Moelln:Knoten > "$(dirname "$0")"/aliases_moelln.json -batctl vd json -n | "$(dirname "$0")"/bat2nodes.py -a "$(dirname "$0")"/aliases.json -a aliases_hl.json -a aliases_moelln.json $GWS - > $DEST/nodes.json.new +"$(dirname "$0")"/bat2nodes.py -a "$(dirname "$0")"/aliases.json -a aliases_hl.json -a aliases_moelln.json > $DEST/nodes.json.new mv $DEST/nodes.json.new $DEST/nodes.json diff --git a/nodedb.py b/nodedb.py index d2584db..40d47cf 100644 --- a/nodedb.py +++ b/nodedb.py @@ -36,11 +36,8 @@ class NodeDB: raise - # import_batman(list(fileinput.input(options['batmanjson']))) - def import_batman(self, lines): - - for line in lines: - x = json.loads(line) + def parse_vis_data(self,vis_data): + for x in vis_data: if 'of' in x: try: @@ -53,8 +50,7 @@ class NodeDB: node.add_mac(x['of']) node.add_mac(x['secondary']) - for line in lines: - x = json.loads(line) + for x in vis_data: if 'router' in x: try: @@ -95,8 +91,7 @@ class NodeDB: node.add_mac(x['neighbor']) self._nodes.append(node) - for line in lines: - x = json.loads(line) + for x in vis_data: if 'router' in x: try: @@ -127,8 +122,7 @@ class NodeDB: self._links.append(link) - for line in lines: - x = json.loads(line) + for x in vis_data: if 'primary' in x: try: