source: genesis/tools/gformat.py@ 9287

Last change on this file since 9287 was 9286, checked in by rick, 13 years ago

The pool has to be formatted smarter, else the name execed the maximum allowed characters.

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 22.2 KB
Line 
1#!/usr/bin/env python
2#
3# vim:ts=2:et:sw=2:ai
4# Wireless Leiden configuration generator, based on yaml files'
5# Rick van der Zwet <info@rickvanderzwet.nl>
6
7# Hack to make the script directory is also threated as a module search path.
8import sys
9import os
10import re
11sys.path.append(os.path.dirname(__file__))
12
13import cgi
14import cgitb
15import copy
16import glob
17import socket
18import string
19import subprocess
20import time
21import rdnap
22from pprint import pprint
23try:
24 import yaml
25except ImportError, e:
26 print e
27 print "[ERROR] Please install the python-yaml or devel/py-yaml package"
28 exit(1)
29
30try:
31 from yaml import CLoader as Loader
32 from yaml import CDumper as Dumper
33except ImportError:
34 from yaml import Loader, Dumper
35
36
37
38if os.environ.has_key('CONFIGROOT'):
39 NODE_DIR = os.environ['CONFIGROOT']
40else:
41 NODE_DIR = os.path.abspath(os.path.dirname(__file__)) + '/../nodes'
42__version__ = '$Id: gformat.py 9286 2011-06-23 19:33:04Z rick $'
43
44
45files = [
46 'authorized_keys',
47 'dnsmasq.conf',
48 'rc.conf.local',
49 'resolv.conf',
50 'wleiden.yaml'
51 ]
52
53# Global variables uses
54OK = 10
55DOWN = 20
56UNKNOWN = 90
57
58
59def get_proxylist():
60 """Get all available proxies proxyX sorting based on X number"""
61 os.chdir(NODE_DIR)
62 proxylist = sorted(glob.glob("proxy*"),
63 key=lambda name: int(''.join([c for c in name if c in string.digits])),
64 cmp=lambda x,y: x - y)
65 return proxylist
66
67
68
69def valid_addr(addr):
70 """ Show which address is valid in which are not """
71 return str(addr).startswith('172.')
72
73
74def get_nodelist():
75 """ Get all available nodes - sorted """
76 os.chdir(NODE_DIR)
77 nodelist = sorted(glob.glob("CNode*"))
78 return nodelist
79
80def get_hostlist():
81 """ Combined hosts and proxy list"""
82 return get_nodelist() + get_proxylist()
83
84def angle_between_points(lat1,lat2,long1,long2):
85 """
86 Return Angle in radians between two GPS coordinates
87 See: http://stackoverflow.com/questions/3809179/angle-between-2-gps-coordinates
88 """
89 dy = lat2 - lat1
90 dx = math.cos(math.pi/180*lat1)*(long2 - long1)
91 angle = math.atan2(dy,dx)
92 return angle
93
94def angle_to_cd(angle):
95 """ Return Dutch Cardinal Direction estimation in 'one digit' of radian angle """
96
97 # For easy conversion get positive degree
98 degrees = math.degrees(angle)
99 if degrees < 0:
100 360 - abs(degrees)
101
102 # Numbers can be confusing calculate from the 4 main directions
103 p = 22.5
104 if degrees < p:
105 return "n"
106 elif degrees < (90 - p):
107 return "no"
108 elif degrees < (90 + p):
109 return "o"
110 elif degrees < (180 - p):
111 return "zo"
112 elif degrees < (180 + p):
113 return "z"
114 elif degrees < (270 - p):
115 return "zw"
116 elif degrees < (270 + p):
117 return "w"
118 elif degrees < (360 - p):
119 return "nw"
120 else:
121 return "n"
122
123
124def generate_title(nodelist):
125 """ Main overview page """
126 items = {'root' : "." }
127 output = """
128<html>
129 <head>
130 <title>Wireless leiden Configurator - GFormat</title>
131 <style type="text/css">
132 th {background-color: #999999}
133 tr:nth-child(odd) {background-color: #cccccc}
134 tr:nth-child(even) {background-color: #ffffff}
135 th, td {padding: 0.1em 1em}
136 </style>
137 </head>
138 <body>
139 <center>
140 <form type="GET" action="%(root)s">
141 <input type="hidden" name="action" value="update">
142 <input type="submit" value="Update Configuration Database (SVN)">
143 </form>
144 <table>
145 <caption><h3>Wireless Leiden Configurator</h3></caption>
146 """ % items
147
148 for node in nodelist:
149 items['node'] = node
150 output += '<tr><td><a href="%(root)s/%(node)s">%(node)s</a></td>' % items
151 for config in files:
152 items['config'] = config
153 output += '<td><a href="%(root)s/%(node)s/%(config)s">%(config)s</a></td>' % items
154 output += "</tr>"
155 output += """
156 </table>
157 <hr />
158 <em>%s</em>
159 </center>
160 </body>
161</html>
162 """ % __version__
163
164 return output
165
166
167
168def generate_node(node):
169 """ Print overview of all files available for node """
170 return "\n".join(files)
171
172
173
174def generate_header(ctag="#"):
175 return """\
176%(ctag)s
177%(ctag)s DO NOT EDIT - Automatically generated by 'gformat'
178%(ctag)s Generated at %(date)s by %(host)s
179%(ctag)s
180""" % { 'ctag' : ctag, 'date' : time.ctime(), 'host' : socket.gethostname() }
181
182
183
184def parseaddr(s):
185 """ Process IPv4 CIDR notation addr to a (binary) number """
186 f = s.split('.')
187 return (long(f[0]) << 24L) + \
188 (long(f[1]) << 16L) + \
189 (long(f[2]) << 8L) + \
190 long(f[3])
191
192
193
194def showaddr(a):
195 """ Display IPv4 addr in (dotted) CIDR notation """
196 return "%d.%d.%d.%d" % ((a >> 24) & 0xff, (a >> 16) & 0xff, (a >> 8) & 0xff, a & 0xff)
197
198
199def is_member(ip, mask, canidate):
200 """ Return True if canidate is part of ip/mask block"""
201 ip_addr = gformat.parseaddr(ip)
202 ip_canidate = gformat.parseaddr(canidate)
203 mask = int(mask)
204 ip_addr = ip_addr & ~((1 << (32 - mask)) - 1)
205 ip_canidate = ip_canidate & ~((1 << (32 - mask)) - 1)
206 return ip_addr == ip_canidate
207
208
209
210
211def netmask2subnet(netmask):
212 """ Given a 'netmask' return corresponding CIDR """
213 return showaddr(0xffffffff & (0xffffffff << (32 - int(netmask))))
214
215
216
217def generate_dnsmasq_conf(datadump):
218 """ Generate configuration file '/usr/local/etc/dnsmasq.conf' """
219 output = generate_header()
220 output += """\
221# DHCP server options
222dhcp-authoritative
223dhcp-fqdn
224domain=dhcp.%(nodename_lower)s.%(domain)s
225domain-needed
226expand-hosts
227
228# Low memory footprint
229cache-size=10000
230 \n""" % datadump
231
232 for iface_key in datadump['iface_keys']:
233 if not datadump[iface_key].has_key('comment'):
234 datadump[iface_key]['comment'] = None
235 output += "## %(interface)s - %(desc)s - %(comment)s\n" % datadump[iface_key]
236
237 try:
238 (dhcp_start, dhcp_stop) = datadump[iface_key]['dhcp'].split('-')
239 (ip, netmask) = datadump[iface_key]['ip'].split('/')
240 datadump[iface_key]['subnet'] = netmask2subnet(netmask)
241 except (AttributeError, ValueError):
242 output += "# not autoritive\n\n"
243 continue
244
245 dhcp_part = ".".join(ip.split('.')[0:3])
246 datadump[iface_key]['dhcp_start'] = dhcp_part + "." + dhcp_start
247 datadump[iface_key]['dhcp_stop'] = dhcp_part + "." + dhcp_stop
248 output += "dhcp-range=%(interface)s,%(dhcp_start)s,%(dhcp_stop)s,%(subnet)s,24h\n\n" % datadump[iface_key]
249
250 return output
251
252
253
254def generate_rc_conf_local(datadump):
255 """ Generate configuration file '/etc/rc.conf.local' """
256 output = generate_header("#");
257 output += """\
258hostname='%(nodetype)s%(nodename)s.%(domain)s'
259location='%(location)s'
260""" % datadump
261
262 # TProxy configuration
263 output += "\n"
264 try:
265 if datadump['tproxy']:
266 output += """\
267tproxy_enable='YES'
268tproxy_range='%(tproxy)s'
269""" % datadump
270 except KeyError:
271 output += "tproxy_enable='NO'\n"
272
273 output += '\n'
274 # lo0 configuration:
275 # - 172.32.255.1/32 is the proxy.wleiden.net deflector
276 # - masterip is special as it needs to be assigned to at
277 # least one interface, so if not used assign to lo0
278 addrs_list = { 'lo0' : ["127.0.0.1/8", "172.31.255.1/32"] }
279 iface_map = {'lo0' : 'lo0'}
280
281 masterip_used = False
282 for iface_key in datadump['iface_keys']:
283 if datadump[iface_key]['ip'].startswith(datadump['masterip']):
284 masterip_used = True
285 break
286 if not masterip_used:
287 addrs_list['lo0'].append(datadump['masterip'] + "/32")
288
289 wlan_count = 0
290 for iface_key in datadump['iface_keys']:
291 ifacedump = datadump[iface_key]
292 interface = ifacedump['interface']
293 # By default no special interface mapping
294 iface_map[interface] = interface
295
296 # Add interface IP to list
297 if addrs_list.has_key(interface):
298 addrs_list[interface].append(ifacedump['ip'])
299 else:
300 addrs_list[interface] = [ifacedump['ip']]
301
302 # Alias only needs IP assignment for now, this might change if we
303 # are going to use virtual accesspoints
304 if "alias" in iface_key:
305 continue
306
307 # XXX: Might want to deduct type directly from interface name
308 if ifacedump['type'] in ['11a', '11b', '11g', 'wireless']:
309 # Create wlanX interface
310 ifacedump['wlanif'] ="wlan%i" % wlan_count
311 iface_map[interface] = ifacedump['wlanif']
312 wlan_count += 1
313
314 # Default to station (client) mode
315 ifacedump['wlanmode'] = "sta"
316 if ifacedump['mode'] in ['master', 'master-wds']:
317 ifacedump['wlanmode'] = "ap"
318 # Default to 802.11b mode
319 ifacedump['mode'] = '11b'
320 if ifacedump['type'] in ['11a', '11b' '11g']:
321 ifacedump['mode'] = ifacedump['type']
322
323 if not ifacedump.has_key('channel'):
324 if ifacedump['type'] == '11a':
325 ifacedump['channel'] = 36
326 else:
327 ifacedump['channel'] = 1
328
329 # Allow special hacks at the back like wds and stuff
330 if not ifacedump.has_key('extra'):
331 ifacedump['extra'] = 'regdomain ETSI country NL'
332
333 output += "wlans_%(interface)s='%(wlanif)s'\n" % ifacedump
334 output += ("create_args_%(wlanif)s='wlanmode %(wlanmode)s mode " +\
335 "%(mode)s ssid %(ssid)s %(extra)s channel %(channel)s'\n") % ifacedump
336
337 elif ifacedump['type'] in ['ethernet', 'eth']:
338 # No special config needed besides IP
339 pass
340 else:
341 assert False, "Unknown type " + ifacedump['type']
342
343 # Print IP address which needs to be assigned over here
344 output += "\n"
345 for iface,addrs in sorted(addrs_list.iteritems()):
346 output += "ipv4_addrs_%s='%s'\n" % (iface_map[iface], " ".join(addrs))
347
348 return output
349
350
351
352def get_yaml(item):
353 """ Get configuration yaml for 'item'"""
354 gfile = os.path.join(NODE_DIR,item,'wleiden.yaml')
355
356 f = open(gfile, 'r')
357 datadump = yaml.load(f,Loader=Loader)
358 f.close()
359
360 return datadump
361
362def store_yaml(datadump):
363 """ Store configuration yaml for 'item'"""
364 gfile = os.path.join(NODE_DIR,item,'wleiden.yaml')
365
366 f = open(gfile, 'w')
367 f.write(generate_wleiden_yaml(datadump))
368 f.close()
369
370
371
372def get_all_configs():
373 """ Get dict with key 'host' with all configs present """
374 configs = dict()
375 for host in get_hostlist():
376 datadump = get_yaml(host)
377 configs[host] = datadump
378 return configs
379
380
381def get_interface_keys(config):
382 """ Quick hack to get all interface keys, later stage convert this to a iterator """
383 return [elem for elem in config.keys() if (elem.startswith('iface_') and not "lo0" in elem)]
384
385
386def get_used_ips(configs):
387 """ Return array of all IPs used in config files"""
388 ip_list = []
389 for config in configs:
390 ip_list.append(config['masterip'])
391 for iface_key in get_interface_keys(config):
392 l = config[iface_key]['ip']
393 addr, mask = l.split('/')
394 # Special case do not process
395 if valid_addr(addr):
396 ip_list.append(addr)
397 else:
398 print "## IP '%s' in '%s' not valid" % (addr, config['nodename'])
399 return sorted(ip_list)
400
401
402
403def write_yaml(item, datadump):
404 """ Write configuration yaml for 'item'"""
405 gfile = os.path.join(NODE_DIR,item,'wleiden.yaml')
406
407 f = open(gfile, 'w')
408 f.write(format_wleiden_yaml(datadump))
409 f.close()
410
411
412
413def generate_resolv_conf(datadump):
414 """ Generate configuration file '/etc/resolv.conf' """
415 output = generate_header("#");
416 output += """\
417search wleiden.net
418# Try local (cache) first
419nameserver 127.0.0.1
420
421# Proxies are recursive nameservers
422# needs to be in resolv.conf for dnsmasq as well
423""" % datadump
424
425 for proxy in get_proxylist():
426 proxy_ip = get_yaml(proxy)['masterip']
427 output += "nameserver %-15s # %s\n" % (proxy_ip, proxy)
428 return output
429
430
431
432def format_yaml_value(value):
433 """ Get yaml value in right syntax for outputting """
434 if isinstance(value,str):
435 output = "'%s'" % value
436 else:
437 output = value
438 return output
439
440
441
442def format_wleiden_yaml(datadump):
443 """ Special formatting to ensure it is editable"""
444 output = "# Genesis config yaml style\n"
445 output += "# vim:ts=2:et:sw=2:ai\n"
446 output += "#\n"
447 iface_keys = [elem for elem in datadump.keys() if elem.startswith('iface_')]
448 for key in sorted(set(datadump.keys()) - set(iface_keys)):
449 output += "%-10s: %s\n" % (key, format_yaml_value(datadump[key]))
450
451 output += "\n\n"
452
453 key_order = [ 'comment', 'interface', 'ip', 'desc', 'sdesc', 'mode', 'type',
454 'extra_type', 'channel', 'ssid', 'dhcp' ]
455
456 for iface_key in sorted(iface_keys):
457 output += "%s:\n" % iface_key
458 for key in key_order + list(sorted(set(datadump[iface_key].keys()) - set(key_order))):
459 if datadump[iface_key].has_key(key):
460 output += " %-11s: %s\n" % (key, format_yaml_value(datadump[iface_key][key]))
461 output += "\n\n"
462
463 return output
464
465
466
467def generate_wleiden_yaml(datadump):
468 """ Generate (petty) version of wleiden.yaml"""
469 output = generate_header("#")
470 output += format_wleiden_yaml(datadump)
471 return output
472
473
474def generate_yaml(datadump):
475 return generate_config(datadump['nodename'], "wleiden.yaml", datadump)
476
477
478
479def generate_config(node, config, datadump=None):
480 """ Print configuration file 'config' of 'node' """
481 output = ""
482 try:
483 # Load config file
484 if datadump == None:
485 datadump = get_yaml(node)
486
487 # Preformat certain needed variables for formatting and push those into special object
488 datadump_extra = copy.deepcopy(datadump)
489 if not datadump_extra.has_key('domain'):
490 datadump_extra['domain'] = 'wleiden.net'
491 datadump_extra['nodename_lower'] = datadump_extra['nodename'].lower()
492 datadump_extra['iface_keys'] = sorted([elem for elem in datadump.keys() if elem.startswith('iface_')])
493
494 if config == 'wleiden.yaml':
495 output += generate_wleiden_yaml(datadump)
496 elif config == 'authorized_keys':
497 f = open("global_keys", 'r')
498 output += f.read()
499 f.close()
500 elif config == 'dnsmasq.conf':
501 output += generate_dnsmasq_conf(datadump_extra)
502 elif config == 'rc.conf.local':
503 output += generate_rc_conf_local(datadump_extra)
504 elif config == 'resolv.conf':
505 output += generate_resolv_conf(datadump_extra)
506 else:
507 assert False, "Config not found!"
508 except IOError, e:
509 output += "[ERROR] Config file not found"
510 return output
511
512
513
514def process_cgi_request():
515 """ When calling from CGI """
516 # Update repository if requested
517 form = cgi.FieldStorage()
518 if form.getvalue("action") == "update":
519 print "Refresh: 5; url=."
520 print "Content-type:text/plain\r\n\r\n",
521 print "[INFO] Updating subverion, please wait..."
522 print subprocess.Popen(['svn', 'up', NODE_DIR], stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0],
523 print "[INFO] All done, redirecting in 5 seconds"
524 sys.exit(0)
525
526
527 uri = os.environ['PATH_INFO'].strip('/').split('/')
528 output = ""
529 if not uri[0]:
530 output += "Content-type:text/html\r\n\r\n"
531 output += generate_title(get_hostlist())
532 elif len(uri) == 1:
533 output += "Content-type:text/plain\r\n\r\n"
534 output += generate_node(uri[0])
535 elif len(uri) == 2:
536 output += "Content-type:text/plain\r\n\r\n"
537 output += generate_config(uri[0], uri[1])
538 else:
539 assert False, "Invalid option"
540 print output
541
542def get_fqdn(datadump):
543 # Proxy naming convention is special
544 if datadump['nodetype'] == 'Proxy':
545 fqdn = datadump['nodename']
546 else:
547 # By default the full name is listed and also a shortname CNAME for easy use.
548 fqdn = datadump['nodetype'] + datadump['nodename']
549 return(fqdn)
550
551
552
553def make_dns(output_dir = 'dns'):
554 items = dict()
555
556 # hostname is key, IP is value
557 wleiden_zone = dict()
558 wleiden_cname = dict()
559
560 pool = dict()
561 for node in get_hostlist():
562 datadump = get_yaml(node)
563
564 # Proxy naming convention is special
565 fqdn = get_fqdn(datadump)
566 if datadump['nodetype'] == 'CNode':
567 wleiden_cname[datadump['nodename']] = fqdn
568
569 wleiden_zone[fqdn] = datadump['masterip']
570
571 # Hacking to get proper DHCP IPs and hostnames
572 for iface_key in get_interface_keys(datadump):
573 iface_name = datadump[iface_key]['interface'].replace(':',"-alias-")
574 (ip, netmask) = datadump[iface_key]['ip'].split('/')
575 try:
576 (dhcp_start, dhcp_stop) = datadump[iface_key]['dhcp'].split('-')
577 datadump[iface_key]['subnet'] = netmask2subnet(netmask)
578 dhcp_part = ".".join(ip.split('.')[0:3])
579 if ip != datadump['masterip']:
580 wleiden_zone["dhcp-gateway-%s.%s" % (iface_name, fqdn)] = ip
581 for i in range(int(dhcp_start), int(dhcp_stop) + 1):
582 wleiden_zone["dhcp-%s-%s.%s" % (i, iface_name, fqdn)] = "%s.%s" % (dhcp_part, i)
583 except (AttributeError, ValueError):
584 # First push it into a pool, to indentify the counter-part later on
585 addr = parseaddr(ip)
586 netmask = int(netmask)
587 addr = addr & ~((1 << (32 - netmask)) - 1)
588 if pool.has_key(addr):
589 pool[addr] += [(iface_name, fqdn, ip)]
590 else:
591 pool[addr] = [(iface_name, fqdn, ip)]
592 continue
593
594
595 def pool_to_name(node, pool_members):
596 """Convert the joined name to a usable pool name"""
597
598 # Get rid of the own entry
599 pool_members = list(set(pool_members) - set([fqdn]))
600
601 target = oldname = ''
602 for node in sorted(pool_members):
603 (name, number) = re.match('^([A-Za-z]+)([0-9]*)$',node).group(1,2)
604 target += "-" + number if name == oldname else "-" + node if target else node
605 oldname = name
606
607 return target
608
609
610 # Automatic naming convention of interlinks namely 2 + remote.lower()
611 for (key,value) in pool.iteritems():
612 if len(value) == 1:
613 (iface_name, fqdn, ip) = value[0]
614 wleiden_zone["2unused-%s.%s" % (iface_name, fqdn)] = ip
615 elif len(value) == 2:
616 (a_iface_name, a_fqdn, a_ip) = value[0]
617 (b_iface_name, b_fqdn, b_ip) = value[1]
618 wleiden_zone["2%s.%s" % (b_fqdn,a_fqdn)] = a_ip
619 wleiden_zone["2%s.%s" % (a_fqdn,b_fqdn)] = b_ip
620 else:
621 pool_members = [k[1] for k in value]
622 for item in value:
623 (iface_name, fqdn, ip) = item
624 pool_name = "2pool-" + showaddr(key).replace('.','-') + "-" + pool_to_name(fqdn,pool_members)
625 wleiden_zone["%s.%s" % (pool_name, fqdn)] = ip
626
627 # Include static DNS entries
628 # XXX: Should they override the autogenerated results?
629 # XXX: Convert input to yaml more useable.
630 # Format:
631 ##; this is a comment
632 ## roomburgh=CNodeRoomburgh1
633 ## apkerk1.CNodeVosko=172.17.176.8 ;this as well
634 dns = yaml.load(open(os.path.join(NODE_DIR,'../dns/staticDNS.yaml'),'r'))
635 for comment, block in dns.iteritems():
636 for k,v in block.iteritems():
637 if valid_addr(v):
638 wleiden_zone[k] = v
639 else:
640 wleiden_cname[k] = v
641
642 details = dict()
643 # 24 updates a day allowed
644 details['serial'] = time.strftime('%Y%m%d%H')
645
646 dns_header = '''
647$TTL 3h
648%(zone)s. SOA sunny.wleiden.net. beheer.lijst.wirelessleiden.nl. ( %(serial)s 1d 12h 1w 3h )
649 ; Serial, Refresh, Retry, Expire, Neg. cache TTL
650
651 NS sunny.wleiden.net.
652 \n'''
653
654
655 if not os.path.isdir('dns'):
656 os.makedirs('dns')
657 details['zone'] = 'wleiden.net'
658 f = open(os.path.join(output_dir,"db." + details['zone']), "w")
659 f.write(dns_header % details)
660
661 for host,ip in wleiden_zone.iteritems():
662 if valid_addr(ip):
663 f.write("%s.wleiden.net. IN A %s \n" % (host.lower(), ip))
664 for source,dest in wleiden_cname.iteritems():
665 f.write("%s.wleiden.net. IN CNAME %s.wleiden.net.\n" % (source.lower(), dest.lower()))
666 f.close()
667
668 # Create whole bunch of specific sub arpa zones. To keep it compliant
669 for s in range(16,32):
670 details['zone'] = '%i.172.in-addr.arpa' % s
671 f = open(os.path.join(output_dir,"db." + details['zone']), "w")
672 f.write(dns_header % details)
673
674 #XXX: Not effient, fix to proper data structure and do checks at other
675 # stages
676 for host,ip in wleiden_zone.iteritems():
677 if valid_addr(ip):
678 if int(ip.split('.')[1]) == s:
679 rev_ip = '.'.join(reversed(ip.split('.')))
680 f.write("%s.in-addr.arpa. IN PTR %s.wleiden.net.\n" % (rev_ip.lower(), host.lower()))
681 f.close()
682
683
684def usage():
685 print """Usage: %s <standalone [port] |test [test arguments]|static|dns>
686Examples:
687\tdns [outputdir] = Generate BIND compliant zone files in dns.
688\tstandalone = Run configurator webserver [default port=8000]
689\tstatic = Generate all config files and store on disk
690\t with format ./static/%%NODE%%/%%FILE%%
691\ttest CNodeRick dnsmasq.conf = Receive output of CGI script
692\t for arguments CNodeRick/dnsmasq.conf
693"""
694 exit(0)
695
696
697
698def main():
699 """Hard working sub"""
700 # Allow easy hacking using the CLI
701 if not os.environ.has_key('PATH_INFO'):
702 if len(sys.argv) < 2:
703 usage()
704
705 if sys.argv[1] == "standalone":
706 import SocketServer
707 import CGIHTTPServer
708 # CGI does not go backward, little hack to get ourself in the right working directory.
709 os.chdir(os.path.dirname(__file__) + '/..')
710 try:
711 PORT = int(sys.argv[2])
712 except (IndexError,ValueError):
713 PORT = 8000
714
715 class MyCGIHTTPRequestHandler(CGIHTTPServer.CGIHTTPRequestHandler):
716 """ Serve this CGI from the root of the webserver """
717 def is_cgi(self):
718 if "favicon" in self.path:
719 return False
720
721 self.cgi_info = (__file__, self.path)
722 self.path = ''
723 return True
724 handler = MyCGIHTTPRequestHandler
725 httpd = SocketServer.TCPServer(("", PORT), handler)
726 httpd.server_name = 'localhost'
727 httpd.server_port = PORT
728
729 print "serving at port", PORT
730 try:
731 httpd.serve_forever()
732 except KeyboardInterrupt:
733 httpd.shutdown()
734 elif sys.argv[1] == "test":
735 os.environ['PATH_INFO'] = "/".join(sys.argv[2:])
736 os.environ['SCRIPT_NAME'] = __file__
737 process_cgi_request()
738 elif sys.argv[1] == "static":
739 items = dict()
740 for node in get_hostlist():
741 items['node'] = node
742 items['wdir'] = "./static/%(node)s" % items
743 if not os.path.isdir(items['wdir']):
744 os.makedirs(items['wdir'])
745 datadump = get_yaml(node)
746 for config in files:
747 items['config'] = config
748 print "## Generating %(node)s %(config)s" % items
749 f = open("%(wdir)s/%(config)s" % items, "w")
750 f.write(generate_config(node, config, datadump))
751 f.close()
752 elif sys.argv[1] == "dns":
753 make_dns(sys.argv[2] if len(sys.argv) > 2 else 'dns')
754 elif sys.argv[1] == "cleanup":
755 # First generate all datadumps
756 datadumps = dict()
757 for host in get_hostlist():
758 datadump = get_yaml(host)
759 datadumps[get_fqdn(datadump)] = datadump
760
761 datadump['latitude'], datadump['longitude'] = rdnap.rd2etrs(datadump['rdnap_x'], datadump['rdnap_y'])
762 write_yaml(host, datadump)
763 else:
764 usage()
765 else:
766 cgitb.enable()
767 process_cgi_request()
768
769
770if __name__ == "__main__":
771 main()
Note: See TracBrowser for help on using the repository browser.