1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- from __future__ import print_function
- import io
- import json
- import string
- import subprocess
- import time
- from .exceptions import SanityCheckError
- class BatmanParser:
- batadv_vis = 'batadv-vis'
- mactranslation = string.maketrans('2367abef', '014589cd')
- def __str__(self):
- return 'BatmanParser \'{0}\''.format(self.batadv_vis)
- def sanitycheck(self):
- """Checks that batadv-vis is executable and gives sane output."""
- testdata = None
- try:
- testdata = subprocess.check_output([self.batadv_vis, '-f', 'jsondoc'])
- except Exception as err:
- raise SanityCheckError(
- self, "batadv-vis not found or incompatible", err)
- try:
- json.loads(testdata)
- except Exception as err:
- raise SanityCheckError(
- self, "batadv-vis does not return valid JSON data", err)
- return True
- def mac2id(self, mac):
- """Derives a nodeid from the given MAC address."""
- temp = str(mac.lower().replace(':', ''))
- # temp = temp[0] + temp[1].translate(self.mactranslation) + temp[2:]
- return temp
- def fetch(self, batadv_dump=None, include_rawdata=False):
- """Fetches the current data from batadv-vis and returns it."""
- data = {}
- ts = int(time.time())
- # call batadv-vis and parse output as JSON
- rawdata = subprocess.check_output([self.batadv_vis, '-f', 'jsondoc'])
- batmandata = json.loads(rawdata)
- # dump raw data into file if requested
- if not batadv_dump is None:
- dumpfile = io.open(batadv_dump, 'w')
- dumpfile.write(rawdata)
- dumpfile.close()
- # parse raw data, convert all MAC into nodeid
- for item in batmandata['vis']:
- itemid = self.mac2id(item['primary'])
- aliases = []
- if 'secondary' in item:
- for mac in item['secondary']:
- aliases.append(self.mac2id(mac))
- neighbours = {}
- if 'neighbors' in item:
- for neighbour in item['neighbors']:
- #if neighbour['router'] != item['primary']:
- # print('node {0}\'s neighbor {1} has unexpected router {2}'.format(itemid, neighbour['neighbor'], neighbour['router']))
- neighbours[neighbour['neighbor']] = float(neighbour['metric'])
- # construct dict entry as expected by BATCAVE
- data[itemid] = {
- 'aliases': aliases,
- 'neighbours': neighbours,
- 'clients': [x for x in item['clients']] if 'clients' in item else [],
- '__UPDATED__': {'batadv': ts,},
- '__RAW__': {'batadv': {itemid: item,}},
- }
- return data
- # standalone test mode
- if __name__ == "__main__":
- b = BatmanParser()
- try:
- b.sanitycheck()
- except SanityCheckError as err:
- print('SANITY-CHECK failed:', str(err))
- import sys
- sys.exit(1)
- bdata = b.fetch()
- print(json.dumps(bdata))
|