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

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

Fixed prefix 'Node' does not could as proxies get included in this list as
well.

  • Property svn:executable set to *
File size: 8.5 KB
Line 
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>
6
7import cgi
8import gformat
9import re
10import sys
11import urllib
12import yaml
13import math
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
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
60def rd2etrs(xrd, yrd, hnap=0.0):
61 """ Convert rd to etrs """
62 # Get cache is exists
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
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
78 item = dict()
79 item['xrd'] = xrd
80 item['yrd'] = yrd
81 item['hnap'] = hnap
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
85 print "### Not in Cache, Fetching coordinate %s, %s from %s" % (xrd, yrd, url)
86 f = urllib.urlopen(url)
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
97 coordinates[(xrd, yrd)] = (lam, phi)
98 write_yaml(CACHE_FILE, coordinates)
99 return (lam, phi)
100
101def make_graph():
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
109 f = open('kmlfile.kml', 'w')
110 f.write("""<?xml version="1.0" encoding="UTF-8"?>
111<kml xmlns="http://earth.google.com/kml/2.0">
112 <Document>
113 <name>WirelessLeiden Nodemap</name>
114 <open>1</open>
115 <description>Generated realtime status of all Wireless Leiden AccessPoints</description>
116 <Style id="node_status_up">
117 <IconStyle>
118 <scale>0.5</scale>
119 <Icon><href>http://www.google.com/mapfiles/kml/paddle/grn-stars-lv.png</href></Icon>
120 </IconStyle>
121 </Style>
122 <Style id="node_status_down">
123 <IconStyle>
124 <scale>0.5</scale>
125 <Icon><href>http://www.google.com/mapfiles/kml/paddle/red-stars-lv.png</href></Icon>
126 </IconStyle>
127 </Style>
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>
133 </Style>
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>
140 <Folder>
141 <name>Nodes</name>
142 <visibility>0</visibility>
143 <description>All active nodes and links</description>
144 """)
145
146 poel = {}
147 link_type = {}
148 node = {}
149
150 nodes = []
151 links = []
152 try:
153 for host in gformat.get_hostlist():
154 fqdn = host + ".wLeiden.NET"
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
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':
172 link_type[addr] = '11a'
173 else:
174 link_type[addr] = datadump[iface_parent]['type']
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)
178 if not status:
179 # By default assume up
180 node_status = "up"
181 elif status['node'][fqdn] == gformat.OK:
182 node_status = "up"
183 elif status['node'][fqdn] == gformat.DOWN:
184 node_status = "down"
185 elif status['node'][fqdn] == gformat.UNKNOWN:
186 node_status = "unknown"
187 else:
188 assert False, "Status cannot be generated"
189
190 print "### Node status is '%s'" % node_status
191 f.write("""
192 <description>All active nodes</description>
193 <Placemark>
194 <name>%(nodetype)s %(nodename)s</name>
195 <description>%(desc)s</description>
196 <styleUrl>%(style)s</styleUrl>
197 <Point><coordinates>%(lam)s,%(phi)s,0</coordinates></Point>
198 </Placemark>
199 """ % {'nodetype' : datadump['nodetype'], 'nodename' : datadump['nodename'], 'desc' : cgi.escape(datadump['location']), 'style' : '#node_status_' + node_status, 'lam' : lam, 'phi' : phi})
200 nodes += [("POINT(%s, %s)" % (lam, phi))]
201 except (KeyError, ValueError), e:
202 print "[FOUT] in '%s' interface '%s'" % (host,iface_key)
203 raise
204 sys.exit(1)
205
206 f.write("""
207 </Folder>
208 <Folder>
209 <name>Links</name>
210 <visibility>0</visibility>
211 <description>All links</description>
212 """)
213 for addr,leden in poel.iteritems():
214 if not gformat.valid_addr(gformat.showaddr(addr)):
215 print "## Adres '%s' met leden '%s' ignored'" % (gformat.showaddr(addr), ','.join(leden))
216 continue
217 if link_type[addr] == '11a':
218 weight = 2
219 elif link_type[addr] == 'eth':
220 weight = 4
221 else:
222 weight = 1
223
224 leden = sorted(set(leden))
225 for index,lid in enumerate(leden[:-1]):
226 for buur in leden[index + 1:]:
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
251 f.write("""
252 <Placemark>
253 <name>%(name)s</name>
254 <visibility>0</visibility>
255 <description>%(desc)s</description>
256 <LineString>
257 <tessellate>0</tessellate>
258 <coordinates> %(lam1)s, %(phi1)s, 0
259 %(lam2)s , %(phi2)s, 0 </coordinates>
260 </LineString>
261 <Style>%(style)s</Style>
262 </Placemark>
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 })
271 f.write("""
272 </Folder>
273 </Document>
274</kml>
275 """)
276 f.close()
277
278
279if __name__ == "__main__":
280 make_graph()
281
Note: See TracBrowser for help on using the repository browser.