source: genesis/nodes/make_map.py@ 8587

Last change on this file since 8587 was 8587, checked in by rick, 14 years ago

Python friendly name (does not like the dashes)

  • Property svn:executable set to *
File size: 7.7 KB
RevLine 
[8280]1#!/usr/bin/env python
2# vim:ts=2:et:sw=2:ai
3#
4# Build topological network graph
5# Rick van der Zwet <info@rickvanderzwet.nl>
[8285]6
7import cgi
8import gformat
[8280]9import re
10import sys
11import urllib
12import yaml
[8293]13import math
[8280]14
15def get_yaml(gfile):
16 """ Get configuration yaml for 'item'"""
17 f = open(gfile, 'r')
18 datadump = yaml.load(f)
19 return datadump
20
21def write_yaml(gfile, datadump):
22 """ Write configuration yaml for 'item'"""
23 f = open(gfile, 'w')
24 f.write(yaml.dump(datadump, default_flow_style=False))
25 f.close()
26
27CACHE_FILE = '/tmp/rd2etrs.yaml'
28coordinates = None
29
[8293]30def etrs2rd(lam, phi):
[8587]31 """ Convert etrs to rd """
[8293]32
[8587]33 item['lam'] = lam
34 item['phi'] = phi
[8293]35 item['func'] = 'etrs2rd'
[8587]36 url = 'http://vanderzwet.net/rdnap/%(func)s/%(xrd)s/%(yrd)s/0/' % item
[8293]37
38 f = urllib.urlopen(url)
39 raw = f.read()
40
[8587]41 rdnap_x,rdnap_y,rdnap_h = raw.split('/')
42 return (rdnap_x, rdnap_y)
[8293]43
44
[8587]45
[8280]46def rd2etrs(xrd, yrd, hnap=0.0):
[8587]47 """
48 Convert rd to etrs
49 JavaScript Version: https://rdinfo.kadaster.nl/rd/transformator.html
50 """
[8302]51 # Get cache is exists
[8280]52 global coordinates
53 if coordinates == None:
54 try:
55 coordinates = get_yaml(CACHE_FILE)
56 except (IOError,AttributeError):
57 coordinates = dict()
58 pass
59
[8302]60 # Check if item in cache
61 xrd = float(str(xrd))
62 yrd = float(str(yrd))
63 if coordinates.has_key((xrd, yrd)):
64 return coordinates[(xrd, yrd)]
65
66 # Get new coordinate
[8280]67 item = dict()
68 item['xrd'] = xrd
69 item['yrd'] = yrd
70 item['hnap'] = hnap
[8293]71 item['func'] = 'rd2etrs'
[8587]72 url = 'http://vanderzwet.net/rdnap/%(func)s/%(xrd)s/%(yrd)s/%(hnap)s/' % item
[8302]73 print "### Not in Cache, Fetching coordinate %s, %s from %s" % (xrd, yrd, url)
[8293]74 f = urllib.urlopen(url)
[8280]75 raw = f.read()
76
[8587]77 lam,phi,h = raw.split('/')
[8293]78 coordinates[(xrd, yrd)] = (lam, phi)
[8280]79 write_yaml(CACHE_FILE, coordinates)
80 return (lam, phi)
81
82def make_graph():
[8320]83 status = None
84 try:
85 stream = file('/tmp/nodemap_status.yaml','r')
86 status = yaml.load(stream)
87 except IOError,e:
88 print "# Error loading status '%s'" % e
89
[8282]90 f = open('kmlfile.kml', 'w')
[8285]91 f.write("""<?xml version="1.0" encoding="UTF-8"?>
[8282]92<kml xmlns="http://earth.google.com/kml/2.0">
93 <Document>
[8285]94 <name>WirelessLeiden Nodemap</name>
[8282]95 <open>1</open>
[8285]96 <description>Generated realtime status of all Wireless Leiden AccessPoints</description>
97 <Style id="node_status_up">
[8282]98 <IconStyle>
[8285]99 <scale>0.5</scale>
100 <Icon><href>http://www.google.com/mapfiles/kml/paddle/grn-stars-lv.png</href></Icon>
[8282]101 </IconStyle>
102 </Style>
[8285]103 <Style id="node_status_down">
[8282]104 <IconStyle>
[8285]105 <scale>0.5</scale>
106 <Icon><href>http://www.google.com/mapfiles/kml/paddle/red-stars-lv.png</href></Icon>
[8282]107 </IconStyle>
108 </Style>
[8285]109 <Style id="node_status_planned">
110 <IconStyle>
111 <scale>0.5</scale>
112 <Icon><href>http://www.google.com/mapfiles/kml/paddle/wht-stars-lv.png</href></Icon>
113 </IconStyle>
[8282]114 </Style>
[8320]115 <Style id="node_status_unknown">
116 <IconStyle>
117 <scale>0.5</scale>
118 <Icon><href>http://www.google.com/mapfiles/kml/paddle/wht-stars-lv.png</href></Icon>
119 </IconStyle>
120 </Style>
[8282]121 <Folder>
[8285]122 <name>Nodes</name>
[8282]123 <visibility>0</visibility>
[8285]124 <description>All active nodes and links</description>
[8282]125 """)
126
[8280]127 poel = {}
128 link_type = {}
129 node = {}
130
131 nodes = []
132 links = []
133 try:
[8296]134 for host in gformat.get_hostlist():
[8321]135 fqdn = host + ".wLeiden.NET"
[8280]136 print "## Processing host", host
137 datadump = gformat.get_yaml(host)
138 iface_keys = [elem for elem in datadump.keys() if (elem.startswith('iface_') and not "lo0" in elem)]
139 for iface_key in iface_keys:
140 l = datadump[iface_key]['ip']
141 addr, mask = l.split('/')
142
143 addr = gformat.parseaddr(addr)
144 mask = int(mask)
145 addr = addr & ~((1 << (32 - mask)) - 1)
146 if poel.has_key(addr):
147 poel[addr] += [host]
148 else:
149 poel[addr] = [host]
150 # Assume all eth2wifibridge to be 11a for a moment
[8285]151 iface_parent = '_'.join(iface_key.split('_')[0:2])
152 if datadump[iface_parent].has_key('extra_type') and datadump[iface_parent]['extra_type'] == 'eth2wifibridge':
[8280]153 link_type[addr] = '11a'
154 else:
[8285]155 link_type[addr] = datadump[iface_parent]['type']
[8280]156 print "### %s [%s] is of type %s" % (gformat.showaddr(addr), iface_key, link_type[addr])
157 lam, phi = rd2etrs(datadump['rdnap_x'], datadump['rdnap_y'])
158 node[host] = (lam, phi)
[8320]159 if not status:
160 # By default assume up
161 node_status = "up"
[8321]162 elif status['node'][fqdn] == gformat.OK:
[8320]163 node_status = "up"
[8321]164 elif status['node'][fqdn] == gformat.DOWN:
[8320]165 node_status = "down"
[8321]166 elif status['node'][fqdn] == gformat.UNKNOWN:
[8320]167 node_status = "unknown"
168 else:
169 assert False, "Status cannot be generated"
[8321]170
171 print "### Node status is '%s'" % node_status
[8282]172 f.write("""
[8285]173 <description>All active nodes</description>
174 <Placemark>
[8460]175 <name>%(nodetype)s %(nodename)s</name>
[8306]176 <description>%(desc)s</description>
[8320]177 <styleUrl>%(style)s</styleUrl>
[8285]178 <Point><coordinates>%(lam)s,%(phi)s,0</coordinates></Point>
179 </Placemark>
[8460]180 """ % {'nodetype' : datadump['nodetype'], 'nodename' : datadump['nodename'], 'desc' : cgi.escape(datadump['location']), 'style' : '#node_status_' + node_status, 'lam' : lam, 'phi' : phi})
[8280]181 nodes += [("POINT(%s, %s)" % (lam, phi))]
182 except (KeyError, ValueError), e:
183 print "[FOUT] in '%s' interface '%s'" % (host,iface_key)
[8285]184 raise
[8280]185 sys.exit(1)
186
[8285]187 f.write("""
188 </Folder>
189 <Folder>
190 <name>Links</name>
191 <visibility>0</visibility>
192 <description>All links</description>
193 """)
[8280]194 for addr,leden in poel.iteritems():
[8321]195 if not gformat.valid_addr(gformat.showaddr(addr)):
196 print "## Adres '%s' met leden '%s' ignored'" % (gformat.showaddr(addr), ','.join(leden))
197 continue
[8280]198 if link_type[addr] == '11a':
[8285]199 weight = 2
200 elif link_type[addr] == 'eth':
[8280]201 weight = 4
202 else:
203 weight = 1
[8285]204
[8280]205 leden = sorted(set(leden))
206 for index,lid in enumerate(leden[:-1]):
207 for buur in leden[index + 1:]:
[8320]208 key = (lid + ".wLeiden.NET", buur + ".wLeiden.NET")
209 rev_key = (key[1],key[0])
210 link_status = None
211 if not status:
212 # Default assume OK
213 link_status = gformat.OK
214 elif status['link'].has_key(key):
215 link_status = status['link'][key]
216 elif status['link'].has_key(rev_key):
217 link_status = status['link'][rev_key]
218 else:
219 # If link is not known assume nothing
220 link_status = gformat.UNKNOWN
221
222
223 if link_status == gformat.OK:
224 color = '#ffff0000' # green
225 elif link_status == gformat.DOWN:
226 color = '#ff0000ff' # red
227 elif link_status == gformat.UNKNOWN:
228 color = '#55000000' # black
229 else:
230 assert False, "Link status not mapped properly"
231
[8282]232 f.write("""
233 <Placemark>
[8285]234 <name>%(name)s</name>
[8282]235 <visibility>0</visibility>
[8285]236 <description>%(desc)s</description>
[8282]237 <LineString>
238 <tessellate>0</tessellate>
[8285]239 <coordinates> %(lam1)s, %(phi1)s, 0
240 %(lam2)s , %(phi2)s, 0 </coordinates>
[8282]241 </LineString>
[8285]242 <Style>%(style)s</Style>
[8282]243 </Placemark>
[8285]244 """ % { 'lam1' : node[lid][0],
245 'phi1' : node[lid][1],
246 'lam2' : node[buur][0],
247 'phi2' : node[buur][1],
248 'name' : "Interlink: %s --- %s" % (lid, buur),
249 'desc' : "%s [%s]" % (gformat.showaddr(addr), link_type[addr]),
250 'style' : "<LineStyle><color>%s</color><width>%s</width></LineStyle>" % (color, weight),
251 })
[8282]252 f.write("""
253 </Folder>
254 </Document>
255</kml>
256 """)
[8280]257 f.close()
258
259
260if __name__ == "__main__":
261 make_graph()
262
Note: See TracBrowser for help on using the repository browser.