source: genesis/tools/gformat.py@ 9285

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

Proper argument checking, as index does not exists when not defined

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