#!/usr/bin/python from __future__ import print_function from copy import deepcopy import io import json import socket import subprocess import time import StringIO def dict_merge(a, b): '''recursively merges dict's. not just simple a['key'] = b['key'], if both a and bhave a key who's value is a dict then dict_merge is called on both values and the result stored in the returned dictionary.''' if not isinstance(b, dict): return b result = deepcopy(a) for k, v in b.iteritems(): if k in result and isinstance(result[k], dict): result[k] = dict_merge(result[k], v) else: result[k] = deepcopy(v) return result class AlfredParser: alfred_datatypes = [ 158, 159 ] prefix = "ffpb.nodes." target_host = "fdca:ffee:ff12:a254::da7a" target_port = 2003 alfred_dump = '/www/alfred.json' whitelist = [ "24:a4:3c:f8:5e:fa", "24:a4:3c:f8:5e:db", "24:a4:3c:d9:4f:69", "24:a4:3c:a3:67:f0", "24:a4:3c:a3:68:07", "24:a4:3c:d2:21:d5" ] def sanitycheck(self): testdata = None try: testdata = subprocess.check_output(['alfred-json', '-z', 'r', str(int(self.alfred_datatypes[0]))]) except Exception as err: raise Exception("alfred-json not found or incompatible: " + str(err)) try: check = json.loads(testdata) except Exception as err: raise Exception("alfred-json does not return valid JSON data: " + str(err)) return True def execute(self): data = { } ts = int(time.time()) for datatype in self.alfred_datatypes: rawdata = subprocess.check_output(['alfred-json', '-z', '-r', str(int(datatype))]) newdata = json.loads(rawdata) data = dict_merge(data, newdata) if not self.alfred_dump is None: jsondata = json.dumps(data, ensure_ascii=False) f = io.open(self.alfred_dump, 'w') f.write(jsondata) f.close() output = StringIO.StringIO() for nodeid in data: if (not self.whitelist is None) and (not nodeid in self.whitelist): #print("Skipping node {0} as it is not in the configured whitelist.".format(nodeid)) continue nodeinfo = data[nodeid] nodestats = None if "statistics" in nodeinfo: nodestats = nodeinfo["statistics"] if not nodestats is None: print(self.prefix, nodeid, ".uptime", " ", int(float(nodestats["uptime"])), " ", ts, sep='', file=output) traffic = None if "traffic" in nodestats: traffic = nodestats["traffic"] if not traffic is None: print(self.prefix, nodeid, ".rxbytes", " ", int(traffic["rx"]["bytes"]), " ", ts, sep='', file=output) print(self.prefix, nodeid, ".rxpackets", " ", int(traffic["rx"]["packets"]), " ", ts, sep='', file=output) print(self.prefix, nodeid, ".txbytes", " ", int(traffic["tx"]["bytes"]), " ", ts, sep='', file=output) print(self.prefix, nodeid, ".txpackets", " ", int(traffic["tx"]["packets"]), " ", ts, sep='', file=output) else: print("Node {0} does not provide statistics information.".format(nodeid)) s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) s.connect((self.target_host, self.target_port)) all_output = output.getvalue() print(all_output) s.sendall(all_output) s.shutdown(socket.SHUT_WR) s.close() output.close() if __name__ == "__main__": a = AlfredParser() a.sanitycheck() a.execute()