xentaur
annotate xentaur.py @ 33:c68d804c3017
* Trying to add classes (bridge class)
* Configuration templates
* Function save() --- dumps network topology
* Configuration templates
* Function save() --- dumps network topology
author | igor |
---|---|
date | Sat Sep 22 02:25:18 2007 +0300 (2007-09-22) |
parents | bf2d7c5bb340 |
children | 244f1602496a |
rev | line source |
---|---|
igor@0 | 1 #!/usr/bin/python |
igor@0 | 2 |
igor@0 | 3 |
igor@2 | 4 import sys,os,time |
igor@0 | 5 import xenomips_vars |
igor@0 | 6 xenomips_vars.N='1' |
igor@0 | 7 sys.path.append('/etc/xen') |
igor@11 | 8 |
igor@33 | 9 xen_config_name='four_quaggasN' |
igor@32 | 10 try: |
igor@32 | 11 exec 'from '+xen_config_name+' import bridges,vbridges_table, hidden_bridges, domains, broken_links, temporary_links, domain_types' |
igor@32 | 12 except: |
igor@32 | 13 print "Can't find module: %s " % (xen_config_name) |
igor@32 | 14 sys.exit(0) |
igor@11 | 15 |
igor@29 | 16 bridges_turned_down=[] |
igor@29 | 17 |
igor@0 | 18 from IPython.Shell import IPShellEmbed |
igor@0 | 19 |
igor@2 | 20 |
igor@2 | 21 screenrc=os.environ['HOME']+"/.screenrc_xentaur" |
igor@2 | 22 |
igor@10 | 23 def run(program, *args): |
igor@10 | 24 pid = os.fork() |
igor@10 | 25 if not pid: |
igor@10 | 26 os.execvp(program, (program,) + args) |
igor@10 | 27 return os.wait()[0] |
igor@10 | 28 |
igor@10 | 29 def run_command(line): |
igor@10 | 30 #cmds=line.split() |
igor@10 | 31 #run(cmds[0],*cmds[1:]) |
igor@10 | 32 run("/bin/sh", "-c", line) |
igor@10 | 33 |
igor@23 | 34 def run_command_return_stdout(line): |
igor@23 | 35 p = os.popen(line) |
igor@23 | 36 output = p.read() |
igor@23 | 37 p.close() |
igor@23 | 38 return output |
igor@23 | 39 |
igor@0 | 40 def create_bridges_script(): |
igor@0 | 41 unbound_bridges=bridges |
igor@4 | 42 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)) |
igor@4 | 43 create_unbound_bridges+="\n"+"\n".join(map(lambda x: "sudo /bin/ip link set "+x+" up", unbound_bridges)) |
igor@0 | 44 |
igor@0 | 45 print """#!/bin/sh |
igor@0 | 46 # create unbound bridges |
igor@0 | 47 %(create_unbound_bridges)s |
igor@0 | 48 """ % {'create_unbound_bridges' : create_unbound_bridges} |
igor@0 | 49 |
igor@0 | 50 |
igor@0 | 51 def create_domains_script(): |
igor@0 | 52 for N in range(len(domains)): |
igor@11 | 53 print "sudo /usr/sbin/xm create "+xen_config_name+" N="+str(N)+" && sleep 1 && sudo /usr/sbin/xm sched-credit -d $(sudo /usr/sbin/xm list | grep "+domains[N]+" | awk '{print $2}') -c 10 && sleep 1" |
igor@0 | 54 |
igor@0 | 55 def destroy_domains_script(): |
igor@0 | 56 for N in range(len(domains)): |
igor@4 | 57 print "sudo /usr/sbin/xm shutdown "+domains[N] |
igor@0 | 58 |
igor@0 | 59 def create_screens_script(): |
igor@7 | 60 N=1 |
igor@0 | 61 screens=[] |
igor@0 | 62 for domain in domains: |
igor@11 | 63 screens.append("screen -t "+domain+" "+str(N)+" sh -c 'while true; do sudo xm console "+domain+" ; echo Retrying in 5 seconds...; sleep 5; done'") |
igor@0 | 64 N+=1 |
igor@0 | 65 screenlist="\n".join(screens) |
igor@0 | 66 |
igor@11 | 67 # |
igor@11 | 68 # Previous terminal acccess commands: |
igor@11 | 69 # ip="192.168.80."+str(200+N) |
igor@11 | 70 # screens.append("screen -t "+domain+" "+str(N)+" sh -c 'while true; do ssh root@"+ip+" ; done'") |
igor@11 | 71 # |
igor@11 | 72 |
igor@4 | 73 #hardstatus string "\%{gk}\%c \%{yk}\%M\%d \%{wk}\%?\%-Lw\%?\%{bw}\%n*\%f\%t\%?(\%u)\%?\%{wk}\%?\%+Lw\%?" |
igor@10 | 74 |
igor@11 | 75 f=open(screenrc, "w"); |
igor@10 | 76 f.write(""" |
igor@2 | 77 hardstatus on |
igor@2 | 78 hardstatus alwayslastline |
igor@2 | 79 |
igor@0 | 80 screen -t console 0 bash |
igor@10 | 81 %s |
igor@10 | 82 """ % (screenlist)) |
igor@10 | 83 f.close() |
igor@0 | 84 |
igor@0 | 85 def graph_node(node): |
igor@0 | 86 i=0 |
igor@0 | 87 domain_type={} |
igor@0 | 88 for domain in domains: |
igor@0 | 89 domain_type[domain]=domain_types[i] |
igor@0 | 90 i+=1 |
nata@31 | 91 return node+" [label=\" "+node+"\",shapefile=\"shapes/all/"+domain_type[node]+".png\",fontcolor=black,fontsize=16]" |
igor@0 | 92 |
igor@29 | 93 def graph_bridge(bridge): |
igor@29 | 94 if bridge in hidden_bridges: |
igor@29 | 95 return "" |
igor@29 | 96 if bridge in bridges_turned_down: |
igor@29 | 97 return "%s [shape=none,shapefile=\"shapes/all/switch_turned_down.png\"]" % (bridge) |
igor@29 | 98 else: |
igor@29 | 99 return "%s [shape=none,shapefile=\"shapes/all/switch.png\"]" % (bridge) |
igor@29 | 100 |
igor@29 | 101 |
igor@0 | 102 def graph(): |
igor@0 | 103 nodelist="" |
igor@0 | 104 bridgelist="" |
igor@0 | 105 linklist="" |
igor@0 | 106 physicallist="" |
igor@0 | 107 networklist="" |
igor@0 | 108 |
igor@0 | 109 nodelist=";\n ".join(map(graph_node,nodes)) |
igor@0 | 110 if nodelist: nodelist += ";" |
igor@0 | 111 |
igor@29 | 112 bridgelist=";\n ".join(map(graph_bridge,bridges)) |
igor@0 | 113 if bridgelist: bridgelist += ";" |
igor@0 | 114 |
igor@0 | 115 links=[] |
igor@0 | 116 for host, bridges_raw in vbridges_table.iteritems(): |
igor@0 | 117 i=0 |
igor@0 | 118 for this_bridge in bridges_raw: |
igor@27 | 119 if this_bridge in hidden_bridges or not this_bridge: |
igor@0 | 120 continue |
igor@28 | 121 if not [ host, bridges_raw.index(this_bridge), this_bridge ] in temporary_links: |
igor@28 | 122 links.append(host+" -- "+this_bridge+" [taillabel=\"fa"+str(bridges_raw.index(this_bridge))+"/0\"]") |
igor@27 | 123 i+=1 |
igor@27 | 124 # if [ host, this_bridge ] in broken_links: |
igor@27 | 125 # links.append(host+" -- "+this_bridge+" [taillabel=\"fa"+str(i)+"/0\",style=dashed]") |
igor@27 | 126 # else: |
igor@27 | 127 # links.append(host+" -- "+this_bridge+" [taillabel=\"fa"+str(i)+"/0\"]") |
igor@0 | 128 |
igor@0 | 129 for link in temporary_links: |
igor@28 | 130 links.append(link[0]+" -- "+link[2]+" [taillabel=\"fa"+str(link[1])+"/0\",color=blue,len=10,w=5,weight=5]") |
igor@0 | 131 |
igor@27 | 132 for link in broken_links: |
igor@28 | 133 links.append(link[0]+" -- "+link[2]+" [taillabel=\"fa"+str(link[1])+"/0\",style=dashed]") |
igor@27 | 134 |
igor@0 | 135 linklist=";\n ".join(links) |
igor@0 | 136 |
igor@0 | 137 graph_dot = { |
igor@0 | 138 'nodelist' : nodelist, |
igor@0 | 139 'bridgelist' : bridgelist, |
igor@0 | 140 'linklist' : linklist, |
igor@0 | 141 'physicallist' : physicallist, |
igor@0 | 142 'networklist' : networklist, |
igor@0 | 143 } |
igor@0 | 144 |
igor@10 | 145 f = open("xenomips.dot", "w"); |
igor@10 | 146 f.write (""" |
igor@0 | 147 graph G { |
igor@0 | 148 edge [len=1.25]; |
igor@0 | 149 splines=true; |
igor@0 | 150 // nodes |
igor@0 | 151 |
igor@0 | 152 node [shape=plaintext,color=white,shapefile="shapes/cisco.bmp/router.png"]; |
igor@0 | 153 %(nodelist)s |
igor@0 | 154 |
igor@0 | 155 // bridges |
igor@0 | 156 |
igor@6 | 157 node [shape=none,shapefile="shapes/all/switch.png"]; |
igor@0 | 158 %(bridgelist)s |
igor@0 | 159 |
igor@0 | 160 // physical |
igor@0 | 161 |
igor@0 | 162 node [shape=rectangle,color=blue]; |
igor@0 | 163 %(physicallist)s |
igor@0 | 164 |
igor@0 | 165 // networks (not bridges, not physical) |
igor@0 | 166 node [shape=rectangle,color=green]; |
igor@0 | 167 %(networklist)s |
igor@0 | 168 |
igor@0 | 169 // links (between nodes and bridges) |
igor@0 | 170 %(linklist)s |
igor@0 | 171 |
igor@0 | 172 }; |
igor@10 | 173 """ % graph_dot) |
igor@10 | 174 f.close() |
igor@10 | 175 run_command("neato -Tpng -o xenomips.png xenomips.dot ") |
igor@0 | 176 |
igor@27 | 177 def autoredraw(): |
igor@27 | 178 graph() |
igor@27 | 179 |
igor@0 | 180 def start_all(): |
igor@0 | 181 create_bridges_script() |
igor@0 | 182 create_screens_script() |
igor@0 | 183 create_domains_script() |
igor@0 | 184 graph() |
igor@0 | 185 print """ |
igor@0 | 186 cat <<NOTE_FOR_USER |
igor@0 | 187 # To view virtual network map, run: |
igor@0 | 188 gqview xenomips.png |
igor@0 | 189 # To attach to VM consoles, run: |
igor@0 | 190 screen -c screenrc |
igor@0 | 191 NOTE_FOR_USER |
igor@0 | 192 """ |
igor@0 | 193 |
igor@0 | 194 def shell(): |
nata@31 | 195 autoredraw() |
igor@0 | 196 ipshell = IPShellEmbed() |
igor@0 | 197 ipshell() |
igor@0 | 198 |
igor@0 | 199 def stop_all(): |
igor@4 | 200 destroy_domains_script() |
igor@0 | 201 |
igor@0 | 202 def show_usage(): |
igor@0 | 203 print """Usage: |
igor@0 | 204 xentaur {start|stop|start-bridges|start-domains|stop-domains|screen|graph} |
igor@0 | 205 """ |
igor@0 | 206 |
igor@33 | 207 def save(): |
igor@33 | 208 print "network =", xen_config_name |
igor@33 | 209 print "domains =", domains |
igor@33 | 210 print "domain_types =", domain_types |
igor@33 | 211 print "bridges =", bridges |
igor@33 | 212 print "vbridges_table =", vbridges_table |
igor@33 | 213 print "hidden_bridges =", hidden_bridges |
igor@33 | 214 print "broken_links =", broken_links |
igor@33 | 215 print "temporary_links =", temporary_links |
igor@33 | 216 print "bridges_turned_down =", bridges_turned_down |
igor@33 | 217 |
igor@33 | 218 #----------------------------------------------------------------------- |
igor@33 | 219 # CLASSES |
igor@33 | 220 |
igor@33 | 221 class Bridge: |
igor@33 | 222 def __init__ (self,name): |
igor@33 | 223 self.name=name |
igor@33 | 224 def up(self): |
igor@33 | 225 bridge_up(self.name) |
igor@33 | 226 def down(self): |
igor@33 | 227 bridge_down(self.name) |
igor@33 | 228 def show(self): |
igor@33 | 229 show_bridge(self.name) |
igor@33 | 230 def dump_start(self,filter=""): |
igor@33 | 231 dump_start(self.name,filter) |
igor@33 | 232 |
igor@33 | 233 |
igor@23 | 234 #----------------------------------------------------------------------- |
igor@23 | 235 # DOMAINS |
igor@23 | 236 |
igor@23 | 237 def get_domain_id(domain): |
igor@23 | 238 return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n") |
igor@23 | 239 |
igor@22 | 240 |
igor@22 | 241 #----------------------------------------------------------------------- |
igor@22 | 242 # BRIDGES and IFACES |
igor@22 | 243 |
igor@22 | 244 def bridge_down(bridge): |
igor@22 | 245 """ |
igor@22 | 246 Turn the bridge <bridge> down |
igor@22 | 247 """ |
igor@29 | 248 if bridge in bridges_turned_down: |
igor@29 | 249 print "Bridge %s is turned down already" % (bridge) |
igor@29 | 250 else: |
igor@29 | 251 bridges_turned_down.append(bridge) |
igor@29 | 252 run_command("sudo ip link set %s down" % bridge) |
igor@29 | 253 autoredraw() |
igor@22 | 254 |
igor@22 | 255 def bridge_up(bridge): |
igor@22 | 256 """ |
igor@22 | 257 Turn the bridge <bridge> up |
igor@22 | 258 """ |
igor@29 | 259 if not (bridge in bridges_turned_down): |
igor@29 | 260 print "Bridge %s is turned up already" % (bridge) |
igor@29 | 261 else: |
igor@29 | 262 bridges_turned_down.remove(bridge) |
igor@29 | 263 run_command("sudo ip link set %s up" % bridge) |
igor@29 | 264 autoredraw() |
igor@22 | 265 |
igor@22 | 266 def show_bridge(bridge): |
igor@22 | 267 """ |
igor@22 | 268 Show the state of the bridge <bridge> |
igor@22 | 269 """ |
igor@22 | 270 run_command("sudo ip link show %s" % bridge) |
igor@22 | 271 |
igor@23 | 272 |
igor@23 | 273 def int_disconnect(domain, int_number): |
igor@23 | 274 """ |
igor@23 | 275 Disconnect the interface with the number <int_number> |
igor@23 | 276 of the domain <domain> from the bridge to which |
igor@23 | 277 it is connected |
igor@23 | 278 """ |
igor@23 | 279 dom_id=get_domain_id(domain) |
igor@23 | 280 bridge=vbridges_table[domain][int_number] |
igor@23 | 281 if not bridge: |
igor@23 | 282 print "Interface %s of the %s domain is not connected" % (int_number, domain) |
igor@23 | 283 return 1 |
igor@23 | 284 run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number)) |
igor@23 | 285 vbridges_table[domain][int_number]='' |
igor@28 | 286 if [ domain, int_number, bridge ] in temporary_links: |
igor@28 | 287 temporary_links.remove([ domain, int_number, bridge ]) |
igor@27 | 288 else: |
igor@28 | 289 broken_links.append([ domain, int_number, bridge ]) |
igor@27 | 290 autoredraw() |
igor@23 | 291 |
igor@23 | 292 def int_connect(domain, int_number, bridge): |
igor@23 | 293 """ |
igor@23 | 294 Connect the interface with the number <int_number> |
igor@24 | 295 of the domain <domain> to the bridge <bridge> |
igor@23 | 296 """ |
igor@23 | 297 dom_id=get_domain_id(domain) |
igor@23 | 298 |
igor@23 | 299 if vbridges_table[domain][int_number]: |
igor@23 | 300 print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number]) |
igor@23 | 301 return 1 |
igor@23 | 302 run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number)) |
igor@23 | 303 vbridges_table[domain][int_number]=bridge |
igor@28 | 304 if [ domain, int_number, bridge ] in broken_links: |
igor@28 | 305 broken_links.remove([ domain, int_number, bridge ]) |
igor@27 | 306 else: |
igor@28 | 307 temporary_links.append([ domain, int_number, bridge ]) |
igor@27 | 308 autoredraw() |
igor@23 | 309 |
igor@24 | 310 def int_reconnect(domain, int_number, bridge): |
igor@24 | 311 """ |
igor@24 | 312 Reconnect the interface with the number <int_number> |
igor@24 | 313 of the domain <domain> from the bridge to which |
igor@24 | 314 it is connected to the bridge <bridge> |
igor@24 | 315 """ |
igor@24 | 316 int_disconnect(domain, int_number) |
igor@24 | 317 int_connect(domain, int_number, bridge) |
igor@24 | 318 |
igor@24 | 319 def show_int(domain, int_number): |
igor@25 | 320 """ |
igor@25 | 321 Show information about the interface <int_nuber> |
igor@25 | 322 of the domain <domain> |
igor@25 | 323 """ |
igor@26 | 324 return vbridges_table[domain][int_number] |
igor@24 | 325 |
igor@28 | 326 |
igor@28 | 327 def dump_start(bridge, filter=""): |
igor@32 | 328 try: |
igor@32 | 329 print "Writing dump... (press Ctrl-C to stop)" |
igor@32 | 330 run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter)) |
igor@32 | 331 except: |
igor@32 | 332 print "Done.\n Dump is written to xentaur.dump" |
igor@28 | 333 return 0 |
igor@28 | 334 |
igor@28 | 335 def dump_stop(): |
igor@28 | 336 return 0 |
igor@33 | 337 |
igor@33 | 338 |
igor@33 | 339 #----------------------------------------------------------------------- |
igor@33 | 340 # CONFIGURATION TEMPLATES |
igor@33 | 341 |
igor@33 | 342 |
igor@33 | 343 def configure_ip_addresses(doms=domains): |
igor@33 | 344 return 0 |
igor@33 | 345 |
igor@33 | 346 def configure_ospf(doms=domains): |
igor@33 | 347 return 0 |
igor@33 | 348 |
igor@33 | 349 def configure_save(doms=domains): |
igor@33 | 350 write_to(doms,"\nwr\n") |
igor@33 | 351 |
igor@0 | 352 #----------------------------------------------------------------------- |
igor@0 | 353 |
igor@0 | 354 |
igor@0 | 355 def add_domain(name,type): |
igor@0 | 356 domains.append(name) |
igor@0 | 357 domain_types.append(type) |
igor@0 | 358 |
igor@0 | 359 def brake_link(domain,bridge): |
igor@0 | 360 broken_links.append([domain,bridge]) |
igor@0 | 361 |
igor@4 | 362 wt_timeout=0.5 |
igor@8 | 363 def write_to(screen,string,return_to_screen=""): |
igor@2 | 364 """ |
igor@2 | 365 write_to(screen,string): |
igor@2 | 366 |
igor@8 | 367 Type *string* to the specified screen(s). |
igor@8 | 368 Screen may be specified with the number *screen*, |
igor@8 | 369 with array of numbers, |
igor@8 | 370 with array of names. |
igor@2 | 371 |
igor@2 | 372 """ |
igor@5 | 373 screen_numbers=[] # number of the screens to write to |
igor@5 | 374 if type(screen) == list: |
igor@5 | 375 screen_numbers=map(lambda x: domains.index(x)+1, screen) |
igor@5 | 376 elif type(screen) == int: |
igor@5 | 377 screen_numbers=[screen] |
igor@5 | 378 else: |
igor@5 | 379 screen_numbers=[domains.index(screen)+1] |
igor@5 | 380 |
igor@5 | 381 for screen_number in screen_numbers: |
igor@5 | 382 run_command("screen -X select "+str(screen_number)) |
igor@5 | 383 time.sleep(wt_timeout) |
igor@5 | 384 for line in string.splitlines(): |
igor@5 | 385 f=open('/tmp/xentaurbuf', 'w') |
igor@5 | 386 f.write(line+"\n") |
igor@5 | 387 f.close() |
igor@5 | 388 run_command("screen -X readreg p /tmp/xentaurbuf") |
igor@5 | 389 time.sleep(wt_timeout) |
igor@5 | 390 run_command("nohup screen -X paste p >& /dev/null") |
igor@5 | 391 time.sleep(wt_timeout) |
igor@5 | 392 |
igor@8 | 393 if return_to_screen != "": |
igor@8 | 394 run_command("screen -X select %s" % (return_to_screen)) |
igor@8 | 395 time.sleep(wt_timeout) |
igor@0 | 396 |
igor@0 | 397 #----------------------------------------------------------------------- |
igor@0 | 398 |
igor@5 | 399 cisco_fa01_up=""" |
igor@5 | 400 ena |
igor@5 | 401 conf t |
igor@5 | 402 int fa0/0 |
igor@5 | 403 no shutdown |
igor@5 | 404 exit |
igor@5 | 405 int fa1/0 |
igor@5 | 406 no shutdown |
igor@5 | 407 exit |
igor@5 | 408 exit |
igor@5 | 409 exit |
igor@5 | 410 """ |
igor@5 | 411 |
igor@5 | 412 cisco_set_ip_on_int=""" |
igor@5 | 413 interface fa%s/0 |
igor@5 | 414 no ip address |
igor@5 | 415 ip address %s 255.255.255.0 |
igor@5 | 416 exit |
igor@5 | 417 """ |
igor@5 | 418 |
igor@33 | 419 |
igor@0 | 420 |
igor@0 | 421 nodes=domains |
igor@0 | 422 |
igor@0 | 423 if len(sys.argv) > 1: |
igor@0 | 424 if sys.argv[1] == 'start': |
igor@0 | 425 start_all() |
igor@0 | 426 if sys.argv[1] == 'stop': |
igor@0 | 427 stop_all() |
igor@0 | 428 if sys.argv[1] == 'start-bridges': |
igor@3 | 429 create_bridges_script() |
igor@0 | 430 if sys.argv[1] == 'start-domains': |
igor@3 | 431 create_domains_script() |
igor@0 | 432 if sys.argv[1] == 'stop-domains': |
igor@3 | 433 destroy_domains_script() |
igor@0 | 434 elif sys.argv[1] == 'screen': |
igor@3 | 435 create_screens_script() |
igor@0 | 436 elif sys.argv[1] == 'graph': |
igor@0 | 437 graph() |
igor@0 | 438 elif sys.argv[1] == 'shell': |
igor@0 | 439 shell() |
igor@0 | 440 |
igor@0 | 441 else: |
igor@0 | 442 show_usage() |
igor@0 | 443 sys.exit(1) |
igor@0 | 444 |
igor@0 | 445 sys.exit(0) |
igor@0 | 446 |
igor@0 | 447 |