xentaur

view xentaur.py @ 40:10444acb35f4

*** empty log message ***
author igor
date Fri Oct 12 17:31:34 2007 +0300 (2007-10-12)
parents 54b7c7ae50ec
children 8c00f233a1d4
line source
1 #!/usr/bin/python
4 import sys,os,time
6 xentaur_path=os.environ['HOME']+"/xentaur"
8 sys.path.append('/etc/xen')
9 sys.path.append(xentaur_path)
11 network='snrs_ipsec_preshared_1'
12 domain='qua1'
13 from xendomain import *
15 bridges_turned_down=[]
17 from IPython.Shell import IPShellEmbed
20 screenrc=os.environ['HOME']+"/.screenrc_xentaur"
22 def run(program, *args):
23 pid = os.fork()
24 if not pid:
25 os.execvp(program, (program,) + args)
26 return os.wait()[0]
28 def run_command(line):
29 #cmds=line.split()
30 #run(cmds[0],*cmds[1:])
31 run("/bin/sh", "-c", line)
33 def run_command_return_stdout(line):
34 p = os.popen(line)
35 output = p.read()
36 p.close()
37 return output
39 def create_bridges_script():
40 unbound_bridges=set(bridges)-set(real_bridges)
41 create_unbound_bridges="\n".join(map(lambda x: "sudo /usr/sbin/brctl show | awk '{print $1}' | grep -qx "+x+" || sudo /usr/sbin/brctl addbr "+x, unbound_bridges))
42 create_unbound_bridges+="\n"+"\n".join(map(lambda x: "sudo /bin/ip link set "+x+" up", unbound_bridges))
44 print """#!/bin/sh
45 # create unbound bridges
46 %(create_unbound_bridges)s
47 """ % {'create_unbound_bridges' : create_unbound_bridges}
50 def create_domains_script():
51 for domain in domains:
52 if not domain in real_nodes:
53 print "sudo /usr/sbin/xm create "+xentaur_path+"/xendomain.py "+" domain="+domain+" network="+network+" && sleep 1 && sudo /usr/sbin/xm sched-credit -d $(sudo /usr/sbin/xm list | grep "+domain+" | awk '{print $2}') -c 10 && sleep 1"
55 def destroy_domains_script():
56 for domain in domains:
57 if not domain in real_nodes:
58 print "sudo /usr/sbin/xm shutdown "+domain
60 def create_screens_script():
61 N=1
62 screens=[]
63 for domain in domains:
64 screens.append("screen -t "+domain+" "+str(N)+" sh -c 'while true; do sudo xm console "+domain+" ; echo Retrying in 5 seconds...; sleep 5; done'")
65 N+=1
66 screenlist="\n".join(screens)
68 #
69 # Previous terminal acccess commands:
70 # ip="192.168.80."+str(200+N)
71 # screens.append("screen -t "+domain+" "+str(N)+" sh -c 'while true; do ssh root@"+ip+" ; done'")
72 #
74 #hardstatus string "\%{gk}\%c \%{yk}\%M\%d \%{wk}\%?\%-Lw\%?\%{bw}\%n*\%f\%t\%?(\%u)\%?\%{wk}\%?\%+Lw\%?"
76 f=open(screenrc, "w");
77 f.write("""
78 hardstatus on
79 hardstatus alwayslastline
81 screen -t console 0 bash
82 %s
83 """ % (screenlist))
84 f.close()
86 def graph_node(node):
87 i=0
88 domain_type={}
89 for domain in domains:
90 domain_type[domain]=domain_types[i]
91 i+=1
92 return node+" [label=\" "+node+"\",shapefile=\"shapes/all/"+domain_type[node]+".png\",fontcolor=black,fontsize=16]"
94 def graph_bridge(bridge):
95 if bridge in hidden_bridges:
96 return ""
97 if bridge in real_bridges:
98 return "%s [shape=none,shapefile=\"shapes/all/real_switch.png\"]" % (bridge)
99 elif bridge in bridges_turned_down:
100 return "%s [shape=none,shapefile=\"shapes/all/switch_turned_down.png\"]" % (bridge)
101 else:
102 return "%s [shape=none,shapefile=\"shapes/all/switch.png\"]" % (bridge)
105 def graph():
106 nodelist=""
107 bridgelist=""
108 linklist=""
109 physicallist=""
110 networklist=""
112 nodelist=";\n ".join(map(graph_node,nodes))
113 if nodelist: nodelist += ";"
115 bridgelist=";\n ".join(map(graph_bridge,bridges))
116 if bridgelist: bridgelist += ";"
118 links=[]
119 for host, bridges_raw in vbridges_table.iteritems():
120 i=0
121 for this_bridge in bridges_raw:
122 if this_bridge in hidden_bridges or not this_bridge:
123 continue
124 if not [ host, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
125 links.append(host+" -- "+this_bridge+" [taillabel=\"fa"+str(bridges_raw.index(this_bridge))+"/0\"]")
126 i+=1
128 for link in temporary_links:
129 links.append(link[0]+" -- "+link[2]+" [taillabel=\"fa"+str(link[1])+"/0\",color=blue,len=10,w=5,weight=5]")
131 for link in broken_links:
132 links.append(link[0]+" -- "+link[2]+" [taillabel=\"fa"+str(link[1])+"/0\",style=dashed]")
135 # bridge-bridge links
136 for host, bridges_raw in bridge_bridge_table.iteritems():
137 i=0
138 for this_bridge in bridges_raw:
139 if this_bridge in hidden_bridges or not this_bridge:
140 continue
141 if not [ host, bridges_raw.index(this_bridge), this_bridge ] in temporary_links:
142 links.append(host+" -- "+this_bridge)
143 i+=1
147 linklist=";\n ".join(links)
149 graph_dot = {
150 'nodelist' : nodelist,
151 'bridgelist' : bridgelist,
152 'linklist' : linklist,
153 'physicallist' : physicallist,
154 'networklist' : networklist,
155 }
157 f = open("xenomips.dot", "w");
158 f.write ("""
159 graph G {
160 edge [len=1.25];
161 splines=true;
162 // nodes
164 node [shape=plaintext,color=white,shapefile="shapes/cisco.bmp/router.png"];
165 %(nodelist)s
167 // bridges
169 node [shape=none,shapefile="shapes/all/switch.png"];
170 %(bridgelist)s
172 // physical
174 node [shape=rectangle,color=blue];
175 %(physicallist)s
177 // networks (not bridges, not physical)
178 node [shape=rectangle,color=green];
179 %(networklist)s
181 // links (between nodes and bridges)
182 %(linklist)s
184 };
185 """ % graph_dot)
186 f.close()
187 run_command("neato -Tpng -o xenomips.png xenomips.dot ")
188 run_command("neato -Tsvg -o xenomips.svg xenomips.dot ")
190 def autoredraw():
191 graph()
193 def start_all():
194 create_bridges_script()
195 create_screens_script()
196 create_domains_script()
197 graph()
198 print """
199 cat <<NOTE_FOR_USER
200 # To view virtual network map, run:
201 gqview xenomips.png
202 # To attach to VM consoles, run:
203 screen -c screenrc
204 NOTE_FOR_USER
205 """
207 def shell():
208 autoredraw()
209 ipshell = IPShellEmbed()
210 ipshell()
212 def stop_all():
213 destroy_domains_script()
215 def show_usage():
216 print """Usage:
217 xentaur {start|stop|start-bridges|start-domains|stop-domains|screen|graph}
218 """
220 def save():
221 print "network =", xen_config_name
222 print "domains =", domains
223 print "domain_types =", domain_types
224 print "bridges =", bridges
225 print "vbridges_table =", vbridges_table
226 print "hidden_bridges =", hidden_bridges
227 print "broken_links =", broken_links
228 print "temporary_links =", temporary_links
229 print "bridges_turned_down =", bridges_turned_down
231 #-----------------------------------------------------------------------
232 # CLASSES
234 class Bridge:
235 def __init__ (self,name):
236 self.name=name
237 def up(self):
238 bridge_up(self.name)
239 def down(self):
240 bridge_down(self.name)
241 def show(self):
242 show_bridge(self.name)
243 def dump_start(self,filter=""):
244 dump_start(self.name,filter)
247 class Domain:
248 def __init__ (self,name):
249 self.name=name
250 def start(self):
251 return ""
252 def stop(self):
253 return ""
254 def start_commandline(self):
255 return ""
256 def graphviz(self):
257 return ""
258 def get_domain_id(self):
259 return get_domain_id(self.name)
261 #-----------------------------------------------------------------------
262 # DOMAINS
264 def get_domain_id(domain):
265 return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n")
268 #-----------------------------------------------------------------------
269 # BRIDGES and IFACES
271 def bridge_down(bridge):
272 """
273 Turn the bridge <bridge> down
274 """
275 if bridge in real_bridges:
276 print "Bridge %s is a real bridge" % (bridge)
277 return -1
278 if bridge in bridges_turned_down:
279 print "Bridge %s is turned down already" % (bridge)
280 else:
281 bridges_turned_down.append(bridge)
282 run_command("sudo ip link set %s down" % bridge)
283 autoredraw()
285 def bridge_up(bridge):
286 """
287 Turn the bridge <bridge> up
288 """
289 if bridge in real_bridges:
290 print "Bridge %s is a real bridge" % (bridge)
291 return -1
292 if not (bridge in bridges_turned_down):
293 print "Bridge %s is turned up already" % (bridge)
294 else:
295 bridges_turned_down.remove(bridge)
296 run_command("sudo ip link set %s up" % bridge)
297 autoredraw()
299 def show_bridge(bridge):
300 """
301 Show the state of the bridge <bridge>
302 """
303 if bridge in real_bridges:
304 print "Bridge %s is a real bridge" % (bridge)
305 return -1
306 run_command("sudo ip link show %s" % bridge)
309 def int_disconnect(domain, int_number):
310 """
311 Disconnect the interface with the number <int_number>
312 of the domain <domain> from the bridge to which
313 it is connected
314 """
315 dom_id=get_domain_id(domain)
316 bridge=vbridges_table[domain][int_number]
317 if not bridge:
318 print "Interface %s of the %s domain is not connected" % (int_number, domain)
319 return 1
320 run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number))
321 vbridges_table[domain][int_number]=''
322 if [ domain, int_number, bridge ] in temporary_links:
323 temporary_links.remove([ domain, int_number, bridge ])
324 else:
325 broken_links.append([ domain, int_number, bridge ])
326 autoredraw()
328 def int_connect(domain, int_number, bridge):
329 """
330 Connect the interface with the number <int_number>
331 of the domain <domain> to the bridge <bridge>
332 """
333 if bridge in real_bridges:
334 print "Bridge %s is a real bridge" % (bridge)
335 return -1
337 dom_id=get_domain_id(domain)
338 if vbridges_table[domain][int_number]:
339 print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number])
340 return 1
341 run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number))
342 vbridges_table[domain][int_number]=bridge
343 if [ domain, int_number, bridge ] in broken_links:
344 broken_links.remove([ domain, int_number, bridge ])
345 else:
346 temporary_links.append([ domain, int_number, bridge ])
347 autoredraw()
349 def int_reconnect(domain, int_number, bridge):
350 """
351 Reconnect the interface with the number <int_number>
352 of the domain <domain> from the bridge to which
353 it is connected to the bridge <bridge>
354 """
355 if bridge in real_bridges:
356 print "Bridge %s is a real bridge" % (bridge)
357 return -1
359 int_disconnect(domain, int_number)
360 int_connect(domain, int_number, bridge)
362 def show_int(domain, int_number):
363 """
364 Show information about the interface <int_nuber>
365 of the domain <domain>
366 """
367 return vbridges_table[domain][int_number]
370 def dump_start(bridge, filter=""):
371 if bridge in real_bridges:
372 print "Bridge %s is a real bridge" % (bridge)
373 return -1
374 try:
375 print "Writing dump... (press Ctrl-C to stop)"
376 run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter))
377 except:
378 print "Done.\n Dump is written to xentaur.dump"
379 return 0
381 def dump_stop():
382 return 0
385 #-----------------------------------------------------------------------
386 # CONFIGURATION TEMPLATES
389 def configure_ip_addresses(doms=domains):
391 cisco_set_ip_on_int="""
392 \n\n\n
393 int fa%s/0
394 no ip address
395 ip address %s 255.255.255.0
396 no shutdown
397 exit
398 """
400 quagga_set_ip_on_int="""
401 int eth%s
402 no ip address
403 ip address %s/24
404 no shutdown
405 exit
406 """
408 for dom in doms:
409 i=domains.index(dom)+1
410 if domain_types[domains.index(dom)] == 'quagga':
411 command = quagga_set_ip_on_int
412 write_to(i,"\nconf t\n")
413 j=0
414 for br in vbridges_table[dom]:
415 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
416 j+=1
417 write_to(i,"\nend\n")
418 else:
419 command = cisco_set_ip_on_int
420 write_to(i,"\nena\nconf t\n")
421 j=0
422 for br in vbridges_table[dom]:
423 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
424 j+=1
425 write_to(i,"\nend\n")
426 return 0
428 def configure_no_ip_addresses(doms=domains):
430 cisco_set_ip_on_int="""
431 \n\n\n
432 int fa%s/0
433 no ip address %s 255.255.255.0
434 exit
435 """
437 quagga_set_ip_on_int="""
438 int eth%s
439 no ip address %s/24
440 exit
441 """
443 for dom in doms:
444 i=domains.index(dom)+1
445 if domain_types[domains.index(dom)] == 'quagga':
446 command = quagga_set_ip_on_int
447 write_to(i,"\nconf t\n")
448 j=0
449 for br in vbridges_table[dom]:
450 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
451 j+=1
452 write_to(i,"\nend\n")
453 else:
454 command = cisco_set_ip_on_int
455 write_to(i,"\nena\nconf t\n")
456 j=0
457 for br in vbridges_table[dom]:
458 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i)))
459 j+=1
460 write_to(i,"\nend\n")
461 return 0
463 def configure_ospf(doms=domains):
464 for dom in doms:
465 if domain_types[domains.index(dom)] == 'quagga':
466 write_to(dom,"\n\nconf t\nrouter ospf\nnetwork 192.168.0.0/16 area 0\nend\n")
467 else:
468 write_to(dom,"\n\nena\nconf t\nrouter ospf 1\nnetwork 192.168.0.0 0.0.255.255 area 0\nend\n")
469 return 0
471 def configure_save(doms=domains):
472 write_to(doms,"\nwr\n")
474 #-----------------------------------------------------------------------
477 def add_domain(name,type):
478 domains.append(name)
479 domain_types.append(type)
481 def brake_link(domain,bridge):
482 broken_links.append([domain,bridge])
484 wt_timeout=0.5
485 def write_to(screen,string,return_to_screen=""):
486 """
487 write_to(screen,string):
489 Type *string* to the specified screen(s).
490 Screen may be specified with the number *screen*,
491 with array of numbers,
492 with array of names.
494 """
495 screen_numbers=[] # number of the screens to write to
496 if type(screen) == list:
497 screen_numbers=map(lambda x: domains.index(x)+1, screen)
498 elif type(screen) == int:
499 screen_numbers=[screen]
500 else:
501 screen_numbers=[domains.index(screen)+1]
503 for screen_number in screen_numbers:
504 run_command("screen -X select "+str(screen_number))
505 time.sleep(wt_timeout)
506 for line in string.splitlines():
507 f=open('/tmp/xentaurbuf', 'w')
508 f.write(line+"\n")
509 f.close()
510 run_command("screen -X readreg p /tmp/xentaurbuf")
511 time.sleep(wt_timeout)
512 run_command("nohup screen -X paste p >& /dev/null")
513 time.sleep(wt_timeout)
515 if return_to_screen != "":
516 run_command("screen -X select %s" % (return_to_screen))
517 time.sleep(wt_timeout)
519 #-----------------------------------------------------------------------
521 cisco_fa01_up="""
522 ena
523 conf t
524 int fa0/0
525 no shutdown
526 exit
527 int fa1/0
528 no shutdown
529 exit
530 exit
531 exit
532 """
534 cisco_set_ip_on_int="""
535 interface fa%s/0
536 no ip address
537 ip address %s 255.255.255.0
538 exit
539 """
543 nodes=domains
545 if len(sys.argv) > 1:
546 if sys.argv[1] == 'start':
547 start_all()
548 if sys.argv[1] == 'stop':
549 stop_all()
550 if sys.argv[1] == 'start-bridges':
551 create_bridges_script()
552 if sys.argv[1] == 'start-domains':
553 create_domains_script()
554 if sys.argv[1] == 'stop-domains':
555 destroy_domains_script()
556 elif sys.argv[1] == 'screen':
557 create_screens_script()
558 elif sys.argv[1] == 'graph':
559 graph()
560 elif sys.argv[1] == 'shell':
561 shell()
563 else:
564 show_usage()
565 sys.exit(1)
567 sys.exit(0)