#!/usr/bin/env python # vim:ts=2:et:sw=2:ai # # Build topological network graph # Rick van der Zwet import cgi import gformat import re import sys import urllib import yaml import math def get_yaml(gfile): """ Get configuration yaml for 'item'""" f = open(gfile, 'r') datadump = yaml.load(f) return datadump def write_yaml(gfile, datadump): """ Write configuration yaml for 'item'""" f = open(gfile, 'w') f.write(yaml.dump(datadump, default_flow_style=False)) f.close() CACHE_FILE = '/tmp/rd2etrs.yaml' coordinates = None def etrs2rd(lam, phi): """ Convert etrs to rd """ item['lam'] = lam item['phi'] = phi item['func'] = 'etrs2rd' url = 'http://vanderzwet.net/rdnap/%(func)s/%(xrd)s/%(yrd)s/0/' % item f = urllib.urlopen(url) raw = f.read() rdnap_x,rdnap_y,rdnap_h = raw.split('/') return (rdnap_x, rdnap_y) def rd2etrs(xrd, yrd, hnap=0.0): """ Convert rd to etrs JavaScript Version: https://rdinfo.kadaster.nl/rd/transformator.html """ # Get cache is exists global coordinates if coordinates == None: try: coordinates = get_yaml(CACHE_FILE) except (IOError,AttributeError): coordinates = dict() pass # Check if item in cache xrd = float(str(xrd)) yrd = float(str(yrd)) if coordinates.has_key((xrd, yrd)): return coordinates[(xrd, yrd)] # Get new coordinate item = dict() item['xrd'] = xrd item['yrd'] = yrd item['hnap'] = hnap item['func'] = 'rd2etrs' url = 'http://vanderzwet.net/rdnap/%(func)s/%(xrd)s/%(yrd)s/%(hnap)s/' % item print "### Not in Cache, Fetching coordinate %s, %s from %s" % (xrd, yrd, url) f = urllib.urlopen(url) raw = f.read() lam,phi,h = raw.split('/') coordinates[(xrd, yrd)] = (lam, phi) write_yaml(CACHE_FILE, coordinates) return (lam, phi) def make_graph(): status = None try: stream = file('/tmp/nodemap_status.yaml','r') status = yaml.load(stream) except IOError,e: print "# Error loading status '%s'" % e f = open('kmlfile.kml', 'w') f.write(""" WirelessLeiden Nodemap 1 Generated realtime status of all Wireless Leiden AccessPoints Nodes 0 All active nodes and links """) poel = {} link_type = {} node = {} nodes = [] links = [] try: for host in gformat.get_hostlist(): fqdn = host + ".wLeiden.NET" print "## Processing host", host datadump = gformat.get_yaml(host) iface_keys = [elem for elem in datadump.keys() if (elem.startswith('iface_') and not "lo0" in elem)] for iface_key in iface_keys: l = datadump[iface_key]['ip'] addr, mask = l.split('/') addr = gformat.parseaddr(addr) mask = int(mask) addr = addr & ~((1 << (32 - mask)) - 1) if poel.has_key(addr): poel[addr] += [host] else: poel[addr] = [host] # Assume all eth2wifibridge to be 11a for a moment iface_parent = '_'.join(iface_key.split('_')[0:2]) if datadump[iface_parent].has_key('extra_type') and datadump[iface_parent]['extra_type'] == 'eth2wifibridge': link_type[addr] = '11a' else: link_type[addr] = datadump[iface_parent]['type'] print "### %s [%s] is of type %s" % (gformat.showaddr(addr), iface_key, link_type[addr]) lam, phi = rd2etrs(datadump['rdnap_x'], datadump['rdnap_y']) node[host] = (lam, phi) if not status: # By default assume up node_status = "up" elif status['node'][fqdn] == gformat.OK: node_status = "up" elif status['node'][fqdn] == gformat.DOWN: node_status = "down" elif status['node'][fqdn] == gformat.UNKNOWN: node_status = "unknown" else: assert False, "Status cannot be generated" print "### Node status is '%s'" % node_status f.write(""" All active nodes %(nodetype)s %(nodename)s %(desc)s %(style)s %(lam)s,%(phi)s,0 """ % {'nodetype' : datadump['nodetype'], 'nodename' : datadump['nodename'], 'desc' : cgi.escape(datadump['location']), 'style' : '#node_status_' + node_status, 'lam' : lam, 'phi' : phi}) nodes += [("POINT(%s, %s)" % (lam, phi))] except (KeyError, ValueError), e: print "[FOUT] in '%s' interface '%s'" % (host,iface_key) raise sys.exit(1) f.write(""" Links 0 All links """) for addr,leden in poel.iteritems(): if not gformat.valid_addr(gformat.showaddr(addr)): print "## Adres '%s' met leden '%s' ignored'" % (gformat.showaddr(addr), ','.join(leden)) continue if link_type[addr] == '11a': weight = 2 elif link_type[addr] == 'eth': weight = 4 else: weight = 1 leden = sorted(set(leden)) for index,lid in enumerate(leden[:-1]): for buur in leden[index + 1:]: key = (lid + ".wLeiden.NET", buur + ".wLeiden.NET") rev_key = (key[1],key[0]) link_status = None if not status: # Default assume OK link_status = gformat.OK elif status['link'].has_key(key): link_status = status['link'][key] elif status['link'].has_key(rev_key): link_status = status['link'][rev_key] else: # If link is not known assume nothing link_status = gformat.UNKNOWN if link_status == gformat.OK: color = '#ffff0000' # green elif link_status == gformat.DOWN: color = '#ff0000ff' # red elif link_status == gformat.UNKNOWN: color = '#55000000' # black else: assert False, "Link status not mapped properly" f.write(""" %(name)s 0 %(desc)s 0 %(lam1)s, %(phi1)s, 0 %(lam2)s , %(phi2)s, 0 """ % { 'lam1' : node[lid][0], 'phi1' : node[lid][1], 'lam2' : node[buur][0], 'phi2' : node[buur][1], 'name' : "Interlink: %s --- %s" % (lid, buur), 'desc' : "%s [%s]" % (gformat.showaddr(addr), link_type[addr]), 'style' : "%s%s" % (color, weight), }) f.write(""" """) f.close() if __name__ == "__main__": make_graph()