#!/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 rd to etrs """ item = dict() (remainder, item['lam_deg']) = math.modf(lam) remainder *= 60 (remainder, item['lam_min']) = math.modf(remainder) item['lam_sec'] = remainder * 60 (remainder, item['phi_deg']) = math.modf(phi) remainder *= 60 (remainder, item['phi_min']) = math.modf(remainder) item['phi_sec'] = remainder * 60 item['func'] = 'etrs2rd' args = "&".join(["%s=%s" % (k,v) for k,v in item.iteritems()]) url = 'http://www.rdnap.nl/cgi-bin/rdetrs.pl?%s' % args print "### Fetching coordinate %s, %s using: %s" % (phi, lam, url) f = urllib.urlopen(url) raw = f.read() r = re.compile('name="([a-z_]+)" value="([0-9\.]+)"') for i in r.finditer(raw): name, value = i.group(1,2) value = float(value) item[name] = value return (item['xrd'], item['yrd']) def rd2etrs(xrd, yrd, hnap=0.0): """ Convert rd to etrs """ # 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' args = "&".join(["%s=%s" % (k,v) for k,v in item.iteritems()]) url = 'http://www.rdnap.nl/cgi-bin/rdetrs.pl?%s' % args print "### Not in Cache, Fetching coordinate %s, %s from %s" % (xrd, yrd, url) f = urllib.urlopen(url) raw = f.read() r = re.compile('name="([a-z_]+)" value="([0-9\.]+)"') for i in r.finditer(raw): name, value = i.group(1,2) value = float(value) item[name] = value lam = item['lam_deg'] + (item['lam_min'] + (item['lam_sec'] / 60)) / 60 phi = item['phi_deg'] + (item['phi_min'] + (item['phi_sec'] / 60)) / 60 coordinates[(xrd, yrd)] = (lam, phi) write_yaml(CACHE_FILE, coordinates) return (lam, phi) def make_graph(): 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(): 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) f.write(""" All active nodes Node %(name)s %(desc)s> #node_status_up %(lam)s,%(phi)s,0 """ % {'name' : host, 'desc' : cgi.escape(datadump['location']), '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 link_type[addr] == '11a': color = '#ff0000ff' weight = 2 elif link_type[addr] == 'eth': color = '#ffff0000' weight = 4 else: color = '#ff000000' weight = 1 leden = sorted(set(leden)) for index,lid in enumerate(leden[:-1]): for buur in leden[index + 1:]: 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()