source: genesis/nodes/make-map.py@ 8399

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

Grumble keys got confused everywhere

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