xentaur

view xentaur.py @ 39:54b7c7ae50ec

brodge-bridge link visualisation
author igor
date Fri Sep 28 13:35:54 2007 +0300 (2007-09-28)
parents f71b298798c2
children 10444acb35f4
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='netw'
12 domain='dyn3'
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 -q "+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 ")
189 def autoredraw():
190 graph()
192 def start_all():
193 create_bridges_script()
194 create_screens_script()
195 create_domains_script()
196 graph()
197 print """
198 cat <<NOTE_FOR_USER
199 # To view virtual network map, run:
200 gqview xenomips.png
201 # To attach to VM consoles, run:
202 screen -c screenrc
203 NOTE_FOR_USER
204 """
206 def shell():
207 autoredraw()
208 ipshell = IPShellEmbed()
209 ipshell()
211 def stop_all():
212 destroy_domains_script()
214 def show_usage():
215 print """Usage:
216 xentaur {start|stop|start-bridges|start-domains|stop-domains|screen|graph}
217 """
219 def save():
220 print "network =", xen_config_name
221 print "domains =", domains
222 print "domain_types =", domain_types
223 print "bridges =", bridges
224 print "vbridges_table =", vbridges_table
225 print "hidden_bridges =", hidden_bridges
226 print "broken_links =", broken_links
227 print "temporary_links =", temporary_links
228 print "bridges_turned_down =", bridges_turned_down
230 #-----------------------------------------------------------------------
231 # CLASSES
233 class Bridge:
234 def __init__ (self,name):
235 self.name=name
236 def up(self):
237 bridge_up(self.name)
238 def down(self):
239 bridge_down(self.name)
240 def show(self):
241 show_bridge(self.name)
242 def dump_start(self,filter=""):
243 dump_start(self.name,filter)
246 class Domain:
247 def __init__ (self,name):
248 self.name=name
249 def start(self):
250 return ""
251 def stop(self):
252 return ""
253 def start_commandline(self):
254 return ""
255 def graphviz(self):
256 return ""
257 def get_domain_id(self):
258 return get_domain_id(self.name)
260 #-----------------------------------------------------------------------
261 # DOMAINS
263 def get_domain_id(domain):
264 return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n")
267 #-----------------------------------------------------------------------
268 # BRIDGES and IFACES
270 def bridge_down(bridge):
271 """
272 Turn the bridge <bridge> down
273 """
274 if bridge in real_bridges:
275 print "Bridge %s is a real bridge" % (bridge)
276 return -1
277 if bridge in bridges_turned_down:
278 print "Bridge %s is turned down already" % (bridge)
279 else:
280 bridges_turned_down.append(bridge)
281 run_command("sudo ip link set %s down" % bridge)
282 autoredraw()
284 def bridge_up(bridge):
285 """
286 Turn the bridge <bridge> up
287 """
288 if bridge in real_bridges:
289 print "Bridge %s is a real bridge" % (bridge)
290 return -1
291 if not (bridge in bridges_turned_down):
292 print "Bridge %s is turned up already" % (bridge)
293 else:
294 bridges_turned_down.remove(bridge)
295 run_command("sudo ip link set %s up" % bridge)
296 autoredraw()
298 def show_bridge(bridge):
299 """
300 Show the state of the bridge <bridge>
301 """
302 if bridge in real_bridges:
303 print "Bridge %s is a real bridge" % (bridge)
304 return -1
305 run_command("sudo ip link show %s" % bridge)
308 def int_disconnect(domain, int_number):
309 """
310 Disconnect the interface with the number <int_number>
311 of the domain <domain> from the bridge to which
312 it is connected
313 """
314 dom_id=get_domain_id(domain)
315 bridge=vbridges_table[domain][int_number]
316 if not bridge:
317 print "Interface %s of the %s domain is not connected" % (int_number, domain)
318 return 1
319 run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number))
320 vbridges_table[domain][int_number]=''
321 if [ domain, int_number, bridge ] in temporary_links:
322 temporary_links.remove([ domain, int_number, bridge ])
323 else:
324 broken_links.append([ domain, int_number, bridge ])
325 autoredraw()
327 def int_connect(domain, int_number, bridge):
328 """
329 Connect the interface with the number <int_number>
330 of the domain <domain> to the bridge <bridge>
331 """
332 if bridge in real_bridges:
333 print "Bridge %s is a real bridge" % (bridge)
334 return -1
336 dom_id=get_domain_id(domain)
337 if vbridges_table[domain][int_number]:
338 print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number])
339 return 1
340 run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number))
341 vbridges_table[domain][int_number]=bridge
342 if [ domain, int_number, bridge ] in broken_links:
343 broken_links.remove([ domain, int_number, bridge ])
344 else:
345 temporary_links.append([ domain, int_number, bridge ])
346 autoredraw()
348 def int_reconnect(domain, int_number, bridge):
349 """
350 Reconnect the interface with the number <int_number>
351 of the domain <domain> from the bridge to which
352 it is connected to the bridge <bridge>
353 """
354 if bridge in real_bridges:
355 print "Bridge %s is a real bridge" % (bridge)
356 return -1
358 int_disconnect(domain, int_number)
359 int_connect(domain, int_number, bridge)
361 def show_int(domain, int_number):
362 """
363 Show information about the interface <int_nuber>
364 of the domain <domain>
365 """
366 return vbridges_table[domain][int_number]
369 def dump_start(bridge, filter=""):
370 if bridge in real_bridges:
371 print "Bridge %s is a real bridge" % (bridge)
372 return -1
373 try:
374 print "Writing dump... (press Ctrl-C to stop)"
375 run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter))
376 except:
377 print "Done.\n Dump is written to xentaur.dump"
378 return 0
380 def dump_stop():
381 return 0
384 #-----------------------------------------------------------------------
385 # CONFIGURATION TEMPLATES
388 def configure_ip_addresses(doms=domains):
389 return 0
391 def configure_ospf(doms=domains):
392 return 0
394 def configure_save(doms=domains):
395 write_to(doms,"\nwr\n")
397 #-----------------------------------------------------------------------
400 def add_domain(name,type):
401 domains.append(name)
402 domain_types.append(type)
404 def brake_link(domain,bridge):
405 broken_links.append([domain,bridge])
407 wt_timeout=0.5
408 def write_to(screen,string,return_to_screen=""):
409 """
410 write_to(screen,string):
412 Type *string* to the specified screen(s).
413 Screen may be specified with the number *screen*,
414 with array of numbers,
415 with array of names.
417 """
418 screen_numbers=[] # number of the screens to write to
419 if type(screen) == list:
420 screen_numbers=map(lambda x: domains.index(x)+1, screen)
421 elif type(screen) == int:
422 screen_numbers=[screen]
423 else:
424 screen_numbers=[domains.index(screen)+1]
426 for screen_number in screen_numbers:
427 run_command("screen -X select "+str(screen_number))
428 time.sleep(wt_timeout)
429 for line in string.splitlines():
430 f=open('/tmp/xentaurbuf', 'w')
431 f.write(line+"\n")
432 f.close()
433 run_command("screen -X readreg p /tmp/xentaurbuf")
434 time.sleep(wt_timeout)
435 run_command("nohup screen -X paste p >& /dev/null")
436 time.sleep(wt_timeout)
438 if return_to_screen != "":
439 run_command("screen -X select %s" % (return_to_screen))
440 time.sleep(wt_timeout)
442 #-----------------------------------------------------------------------
444 cisco_fa01_up="""
445 ena
446 conf t
447 int fa0/0
448 no shutdown
449 exit
450 int fa1/0
451 no shutdown
452 exit
453 exit
454 exit
455 """
457 cisco_set_ip_on_int="""
458 interface fa%s/0
459 no ip address
460 ip address %s 255.255.255.0
461 exit
462 """
466 nodes=domains
468 if len(sys.argv) > 1:
469 if sys.argv[1] == 'start':
470 start_all()
471 if sys.argv[1] == 'stop':
472 stop_all()
473 if sys.argv[1] == 'start-bridges':
474 create_bridges_script()
475 if sys.argv[1] == 'start-domains':
476 create_domains_script()
477 if sys.argv[1] == 'stop-domains':
478 destroy_domains_script()
479 elif sys.argv[1] == 'screen':
480 create_screens_script()
481 elif sys.argv[1] == 'graph':
482 graph()
483 elif sys.argv[1] == 'shell':
484 shell()
486 else:
487 show_usage()
488 sys.exit(1)
490 sys.exit(0)