| rev | line source | 
| igor@0 | 1 #!/usr/bin/python | 
| igor@60 | 2 # vim: set fileencoding=utf-8 : | 
| igor@0 | 3 | 
| igor@2 | 4 import sys,os,time | 
| igor@35 | 5 | 
| igor@35 | 6 xentaur_path=os.environ['HOME']+"/xentaur" | 
| igor@35 | 7 | 
| igor@0 | 8 sys.path.append('/etc/xen') | 
| igor@35 | 9 sys.path.append(xentaur_path) | 
| igor@11 | 10 | 
| igor@56 | 11 #network='snrs_ipsec_rsa_1' | 
| igor@56 | 12 node_object={} | 
| igor@56 | 13 link_object={} | 
| igor@56 | 14 bridge_object={} | 
| igor@56 | 15 | 
| igor@56 | 16 network='icnd2' | 
| igor@56 | 17 domain='sw1' | 
| igor@35 | 18 from xendomain import * | 
| igor@35 | 19 | 
| igor@29 | 20 bridges_turned_down=[] | 
| igor@29 | 21 | 
| igor@0 | 22 from IPython.Shell import IPShellEmbed | 
| igor@0 | 23 | 
| igor@2 | 24 | 
| igor@2 | 25 screenrc=os.environ['HOME']+"/.screenrc_xentaur" | 
| igor@2 | 26 | 
| igor@10 | 27 def run(program, *args): | 
| igor@10 | 28     pid = os.fork() | 
| igor@10 | 29     if not pid: | 
| igor@10 | 30         os.execvp(program, (program,) +  args) | 
| igor@10 | 31     return os.wait()[0] | 
| igor@10 | 32 | 
| igor@10 | 33 def run_command(line): | 
| igor@10 | 34     #cmds=line.split() | 
| igor@10 | 35     #run(cmds[0],*cmds[1:]) | 
| igor@10 | 36     run("/bin/sh", "-c", line) | 
| igor@10 | 37 | 
| igor@23 | 38 def run_command_return_stdout(line): | 
| igor@23 | 39     p = os.popen(line) | 
| igor@23 | 40     output = p.read() | 
| igor@23 | 41     p.close() | 
| igor@23 | 42     return output | 
| igor@23 | 43 | 
| igor@49 | 44 ################################################################################ | 
| igor@49 | 45 #Xentaur command-line commands | 
| igor@49 | 46 | 
| igor@49 | 47 ## Start | 
| igor@49 | 48 | 
| igor@49 | 49 def start_bridges(): | 
| igor@38 | 50     unbound_bridges=set(bridges)-set(real_bridges) | 
| igor@56 | 51     script="" | 
| igor@56 | 52     script="\n".join(map(lambda x: "sudo brctl show | awk '{print $1}' | grep -qx "+x+" || sudo brctl addbr "+x, unbound_bridges)) | 
| igor@56 | 53     script+="\n"+"\n".join(map(lambda x: "sudo brctl stp "+x+" off", unbound_bridges)) | 
| igor@56 | 54     script+="\n"+"\n".join(map(lambda x: "sudo ip link set "+x+" up", unbound_bridges)) | 
| igor@0 | 55 | 
| igor@0 | 56     print """#!/bin/sh | 
| igor@0 | 57 # create unbound bridges | 
| igor@56 | 58 %s | 
| igor@56 | 59 """ % (script) | 
| igor@0 | 60 | 
| igor@49 | 61 def start_domain(domain): | 
| igor@49 | 62     print "sudo xm create "+xentaur_path+"/xendomain.py "+" domain="+domain+" network="+network+" && sleep 1 && sudo xm sched-credit -d $(sudo xm list | grep "+domain+" | awk '{print $2}') -c 10 && sleep 1" | 
| igor@0 | 63 | 
| igor@49 | 64 def start_domains(doms=domains): | 
| igor@49 | 65     for domain in doms: | 
| igor@38 | 66         if not domain in real_nodes: | 
| igor@49 | 67             start_domain(domain) | 
| igor@0 | 68 | 
| igor@49 | 69 def start_all(): | 
| igor@49 | 70     graph() | 
| igor@49 | 71     screen() | 
| igor@49 | 72     start_bridges() | 
| igor@49 | 73     start_domains() | 
| igor@49 | 74 | 
| igor@49 | 75 ## Stop | 
| igor@49 | 76 | 
| igor@49 | 77 def stop_domain(domain,wait=0): | 
| igor@49 | 78     if wait: | 
| igor@49 | 79         print "sudo xm shutdown -w "+domain | 
| igor@49 | 80     else: | 
| igor@49 | 81         print "sudo xm shutdown "+domain | 
| igor@49 | 82 | 
| igor@49 | 83 def stop_domains(doms=domains, wait=0): | 
| igor@49 | 84     for domain in doms: | 
| igor@38 | 85         if not domain in real_nodes: | 
| igor@49 | 86             stop_domain(domain,wait) | 
| igor@0 | 87 | 
| igor@49 | 88 def stop_bridges(): | 
| igor@49 | 89     ###FIXME### | 
| igor@49 | 90     return 0 | 
| igor@49 | 91 | 
| igor@49 | 92 def stop_all(wait=0): | 
| igor@49 | 93     stop_domains(domains, wait) | 
| igor@49 | 94     stop_bridges() | 
| igor@49 | 95 | 
| igor@49 | 96 def restart_all(): | 
| igor@49 | 97     stop_all(1) | 
| igor@49 | 98     start_all() | 
| igor@49 | 99 | 
| igor@56 | 100 #################################################### | 
| igor@56 | 101 | 
| igor@56 | 102 def create_objects(): | 
| igor@56 | 103     create_node_objects() | 
| igor@56 | 104     create_bridge_objects() | 
| igor@56 | 105     create_link_objects() | 
| igor@56 | 106 | 
| igor@56 | 107 def create_node_objects(): | 
| igor@56 | 108     for dom in domains: | 
| igor@56 | 109         node_object[dom]=Node(dom) | 
| igor@56 | 110 | 
| igor@56 | 111 def create_bridge_objects(): | 
| igor@56 | 112     for bridge in bridges: | 
| igor@56 | 113         bridge_object[bridge]=Bridge(bridge) | 
| igor@56 | 114 | 
| igor@56 | 115 def create_link_objects(): | 
| igor@56 | 116 | 
| igor@56 | 117     for node, bridges_raw in vbridges_table.iteritems(): | 
| igor@56 | 118         interface=0 | 
| igor@56 | 119         j=0 | 
| igor@56 | 120         for this_bridge in bridges_raw: | 
| igor@56 | 121             int_label="" | 
| igor@56 | 122             if this_bridge.find(':') != -1: | 
| igor@56 | 123                 res = this_bridge.split(':') | 
| igor@56 | 124                 this_bridge= res[0] | 
| igor@56 | 125                 bridges_raw[j] = this_bridge | 
| igor@56 | 126                 int_label  = res[1] | 
| igor@56 | 127             if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links: | 
| igor@56 | 128                 name="%s %s %s" % (node,interface,this_bridge) | 
| igor@56 | 129                 link_object[name]=Link(name,node,interface,this_bridge,int_label) | 
| igor@56 | 130                 interface+=1 | 
| igor@56 | 131         vbridges_table[node]=bridges_raw | 
| igor@56 | 132 | 
| igor@56 | 133     for node, bridges_raw in bridge_bridge_table.iteritems(): | 
| igor@56 | 134         interface=0 | 
| igor@56 | 135         j=0 | 
| igor@56 | 136         for this_bridge in bridges_raw: | 
| igor@56 | 137             int_label="" | 
| igor@56 | 138             if this_bridge.find(':') != -1: | 
| igor@56 | 139                 res = this_bridge.split(':') | 
| igor@56 | 140                 this_bridge= res[0] | 
| igor@56 | 141                 bridges_raw[j] = this_bridge | 
| igor@56 | 142                 int_label  = res[1] | 
| igor@56 | 143             if not [ node, bridges_raw.index(this_bridge), this_bridge ] in temporary_links: | 
| igor@56 | 144                 name="%s %s %s" % (node,interface,this_bridge) | 
| igor@56 | 145                 link_object[name]=Link(name,node,interface,this_bridge,int_label) | 
| igor@56 | 146                 interface+=1 | 
| igor@56 | 147         bridge_bridge_table[node]=bridges_raw | 
| igor@56 | 148 | 
| igor@56 | 149     for node,interface,bridge in temporary_links: | 
| igor@56 | 150         name="%s %s %s" % (node,interface,bridge) | 
| igor@56 | 151         link_object[name]=Link(name,node,interface,this_bridge) | 
| igor@56 | 152 | 
| igor@56 | 153     for node,interface,bridge in broken_links: | 
| igor@56 | 154         name="%s %s %s" % (node,interface,bridge) | 
| igor@56 | 155         link_object[name]=Link(name,node,interface,this_bridge) | 
| igor@56 | 156 | 
| igor@56 | 157 | 
| igor@56 | 158 #################################################### | 
| igor@56 | 159 | 
| igor@49 | 160 def screen(): | 
| igor@60 | 161     wait_seconds=1 | 
| igor@0 | 162     screens=[] | 
| igor@0 | 163     for domain in domains: | 
| igor@56 | 164         screens.append("screen -t %s %s sh -c 'while true; do %s ; echo Retrying in %s secods...; sleep %s ; clear; done'" % | 
| igor@60 | 165                                  (domain,domains.index(domain)+1,node_object[domain].console_string(),wait_seconds,wait_seconds)) | 
| igor@0 | 166     screenlist="\n".join(screens) | 
| igor@0 | 167 | 
| igor@49 | 168     hardstatus='hardstatus string "%{rk}Xentaur%{bk}@%H %{gk}%c %{yk}%d.%m %{wk}%?%-Lw%?%{bw}%n*%f%t%?(%u)%?%{wk}%?%+Lw%?"' | 
| igor@10 | 169 | 
| igor@11 | 170     f=open(screenrc, "w"); | 
| igor@10 | 171     f.write(""" | 
| igor@2 | 172 hardstatus on | 
| igor@2 | 173 hardstatus alwayslastline | 
| igor@49 | 174 %s | 
| igor@2 | 175 | 
| igor@60 | 176 screen -t console 0 sh -c 'while true; do cd %s; ./xentaur.py shell ; echo Retrying in %s secods...; sleep %s ; clear; done' | 
| igor@60 | 177 #screen -t xentaur - sh -c 'while true; do bash ; echo Retrying in %s secods...; sleep %s ; clear; done' | 
| igor@10 | 178 %s | 
| igor@60 | 179 """ % (hardstatus,xentaur_path,wait_seconds,wait_seconds,wait_seconds,wait_seconds,screenlist)) | 
| igor@10 | 180     f.close() | 
| igor@49 | 181     print "# GNU Screen config file is written to: %s" % screenrc | 
| igor@0 | 182 | 
| igor@0 | 183 def graph(): | 
| igor@0 | 184     nodelist="" | 
| igor@0 | 185     bridgelist="" | 
| igor@0 | 186     linklist="" | 
| igor@0 | 187     physicallist="" | 
| igor@0 | 188     networklist="" | 
| igor@0 | 189 | 
| igor@56 | 190     nodelist=";\n    ".join(map(lambda node: node_object[node].graphviz_string(),nodes)) | 
| igor@0 | 191     if nodelist: nodelist += ";" | 
| igor@56 | 192     bridgelist=";\n    ".join(map(lambda bridge: bridge_object[bridge].graphviz_string(),bridges)) | 
| igor@0 | 193     if bridgelist: bridgelist += ";" | 
| igor@56 | 194     linklist=";\n    ".join(map(lambda link: link_object[link].graphviz_string(),link_object.keys())) | 
| igor@56 | 195     if linklist: linklist += ";" | 
| igor@0 | 196 | 
| igor@46 | 197     f = open(network+".dot", "w"); | 
| igor@10 | 198     f.write (""" | 
| igor@0 | 199 graph G { | 
| igor@0 | 200     edge [len=1.25]; | 
| igor@0 | 201     splines=true; | 
| igor@0 | 202 // nodes | 
| igor@56 | 203 //    node [shape=plaintext,color=white,shapefile="shapes/cisco.bmp/router.png"]; | 
| igor@56 | 204     %s | 
| igor@0 | 205 | 
| igor@0 | 206 // bridges | 
| igor@56 | 207 //    node [shape=none,shapefile="shapes/all/switch.png"]; | 
| igor@56 | 208     %s | 
| igor@0 | 209 | 
| igor@0 | 210 // physical | 
| igor@0 | 211     node [shape=rectangle,color=blue]; | 
| igor@56 | 212     %s | 
| igor@0 | 213 | 
| igor@0 | 214 // networks (not bridges, not physical) | 
| igor@0 | 215     node [shape=rectangle,color=green]; | 
| igor@56 | 216     %s | 
| igor@0 | 217 | 
| igor@0 | 218 // links (between nodes and bridges) | 
| igor@56 | 219     %s | 
| igor@0 | 220 | 
| igor@0 | 221 }; | 
| igor@56 | 222 """ % (nodelist, bridgelist, physicallist, networklist, linklist)) | 
| igor@10 | 223     f.close() | 
| igor@46 | 224     run_command("neato -Tpng -o %s.png %s.dot "%(network,network)) | 
| igor@46 | 225     run_command("neato -Tjpg -o %s.jpg %s.dot "%(network,network)) | 
| igor@46 | 226     run_command("neato -Tsvg -o %s.svg %s.dot "%(network,network)) | 
| igor@56 | 227     run_command("neato -Tcmapx -o %s.cmapx -NURL=http://google.com %s.dot "%(network,network)) | 
| igor@49 | 228     print "# Network map is written to files: %s.{png,svg,jpg,dot}" % network | 
| igor@0 | 229 | 
| igor@27 | 230 def autoredraw(): | 
| igor@27 | 231     graph() | 
| igor@27 | 232 | 
| igor@0 | 233 def shell(): | 
| nata@31 | 234     autoredraw() | 
| igor@0 | 235     ipshell = IPShellEmbed() | 
| igor@0 | 236     ipshell() | 
| igor@0 | 237 | 
| igor@60 | 238 def version(): | 
| igor@60 | 239     print "Xentaur 0.1-PRE" | 
| igor@60 | 240     print "(Godzilla-mutant)  _" | 
| igor@60 | 241     print "                 / * \\" | 
| igor@60 | 242     print "                /   .-" | 
| igor@60 | 243     print "               /   |" | 
| igor@60 | 244     print "              | \\ \\\\ \\" | 
| igor@60 | 245     print "     _ -------|  \\ \\\\ \\" | 
| igor@60 | 246     print " / /              \\_\\ -" | 
| igor@60 | 247     print "/ |\\           |   |" | 
| igor@60 | 248     print "| |  \\ .-----. | \\ |" | 
| igor@60 | 249     print "  |  /        \\ \\ \\ \\" | 
| igor@60 | 250     print "  \\/|.\\        \\ \\ \\ \\" | 
| igor@60 | 251     print "   \\| - .       \\_\\ \\_\\" | 
| igor@60 | 252     print "-----------------------------------------------" | 
| igor@60 | 253 | 
| igor@60 | 254 | 
| igor@60 | 255 def info(): | 
| igor@60 | 256     version() | 
| igor@60 | 257 | 
| igor@60 | 258     print "Network name: ", network | 
| igor@60 | 259     print "-----------------------------------------------" | 
| igor@60 | 260     print | 
| igor@60 | 261     print "Nodes: ", len(domains) | 
| igor@60 | 262     print "  * virtual nodes: ", len(domains)-len(real_nodes) | 
| igor@60 | 263     print "  * real nodes:", len(real_nodes) | 
| igor@60 | 264     print | 
| igor@60 | 265     print "Bridges:", len(bridges) | 
| igor@60 | 266     print "  * virtual bridges:", len(bridges)-len(real_bridges)-len(cross_bridges) | 
| igor@60 | 267     print "  * real switches:", len(real_bridges) | 
| igor@60 | 268     print "  * direct links:", len(cross_bridges) | 
| igor@60 | 269 | 
| igor@0 | 270 def show_usage(): | 
| igor@0 | 271     print """Usage: | 
| igor@49 | 272     xentaur <command> [<argument>] | 
| igor@49 | 273 | 
| igor@49 | 274 Commands: | 
| igor@49 | 275     start-all       --  start bridges and domains | 
| igor@49 | 276     start-domains   --  start domains only | 
| igor@49 | 277     start-bridges   --  start bridges only | 
| igor@49 | 278     stop-all        --  stop bridges and domains | 
| igor@49 | 279     stop-domains    --  stop domains only | 
| igor@49 | 280     stop-bridges    --  stop bridges only (domains have to be stopped already) | 
| igor@49 | 281     restart-all     --  restart bridges and domains | 
| igor@49 | 282 | 
| igor@49 | 283     start <domain>  --  start the <domain> | 
| igor@49 | 284     stop <domain>   --  stop the <domain> | 
| igor@49 | 285 | 
| igor@49 | 286     graph           --  generate network scheme (result is in <network>.{png,jpg,svg}) | 
| igor@49 | 287     screen          --  generate GNU Screen config file (~/.screenrc_xentaur) | 
| igor@49 | 288     shell           --  run Xentaur shell | 
| igor@49 | 289 | 
| igor@0 | 290 """ | 
| igor@0 | 291 | 
| igor@33 | 292 def save(): | 
| igor@33 | 293     print "network =",          xen_config_name | 
| igor@33 | 294     print "domains =",          domains | 
| igor@33 | 295     print "domain_types =",     domain_types | 
| igor@33 | 296     print "bridges =",          bridges | 
| igor@33 | 297     print "vbridges_table =",   vbridges_table | 
| igor@33 | 298     print "hidden_bridges =",   hidden_bridges | 
| igor@33 | 299     print "broken_links =",     broken_links | 
| igor@33 | 300     print "temporary_links =",  temporary_links | 
| igor@33 | 301     print "bridges_turned_down =", bridges_turned_down | 
| igor@33 | 302 | 
| igor@33 | 303 #----------------------------------------------------------------------- | 
| igor@33 | 304 # CLASSES | 
| igor@33 | 305 | 
| igor@33 | 306 class Bridge: | 
| igor@33 | 307     def __init__ (self,name): | 
| igor@33 | 308         self.name=name | 
| igor@33 | 309     def up(self): | 
| igor@33 | 310         bridge_up(self.name) | 
| igor@33 | 311     def down(self): | 
| igor@33 | 312         bridge_down(self.name) | 
| igor@33 | 313     def show(self): | 
| igor@33 | 314         show_bridge(self.name) | 
| igor@33 | 315     def dump_start(self,filter=""): | 
| igor@33 | 316         dump_start(self.name,filter) | 
| igor@33 | 317 | 
| igor@56 | 318     def is_hidden(self): | 
| igor@56 | 319         return self.name in hidden_bridges | 
| igor@56 | 320     def is_real(self): | 
| igor@56 | 321         return self.name in real_bridges | 
| igor@56 | 322     def is_turned_down(self): | 
| igor@56 | 323         return self.name in bridges_turned_down | 
| igor@56 | 324     def is_cross(self): | 
| igor@56 | 325         return self.name in cross_bridges | 
| igor@33 | 326 | 
| igor@56 | 327     def graphviz_string(self): | 
| igor@56 | 328         if self.is_hidden(): | 
| igor@56 | 329             return "" | 
| igor@56 | 330         elif self.is_cross(): | 
| igor@56 | 331             return "%s [shape=circle,height=0.03,color=black,fillcolor=black,style=filled,label=\"\"]" % (self.name) | 
| igor@56 | 332         elif self.is_real(): | 
| igor@56 | 333             return "%s [color=white,shape=none,shapefile=\"shapes/all/real_switch.png\"]" % (self.name) | 
| igor@56 | 334         elif self.is_turned_down(): | 
| igor@56 | 335             return "%s [color=white,shape=none,shapefile=\"shapes/all/switch_turned_down.png\"]" % (self.name) | 
| igor@56 | 336         else: | 
| igor@56 | 337             return "%s [color=white,shape=none,shapefile=\"shapes/all/switch.png\"]" % (self.name) | 
| igor@56 | 338 | 
| igor@56 | 339 | 
| igor@56 | 340 class Node: | 
| igor@38 | 341     def __init__ (self,name): | 
| igor@38 | 342         self.name=name | 
| igor@56 | 343         self.type=domain_types[domains.index(name)] | 
| igor@38 | 344     def start(self): | 
| igor@38 | 345         return "" | 
| igor@38 | 346     def stop(self): | 
| igor@38 | 347         return "" | 
| igor@38 | 348     def start_commandline(self): | 
| igor@38 | 349         return "" | 
| igor@38 | 350     def get_domain_id(self): | 
| igor@38 | 351         return get_domain_id(self.name) | 
| igor@56 | 352     def graphviz_string(self): | 
| igor@56 | 353         return self.name+" [color=white,shape=plaintext,label=\"  "+self.name+"\",shapefile=\"shapes/all/"+\ | 
| igor@56 | 354         domain_types[domains.index(self.name)]+".png\",fontcolor=black,fontsize=16,target=\"http://google.com\"]" | 
| igor@56 | 355     def console_string(self): | 
| igor@56 | 356         if self.type == 'quagga' or self.type == 'xenomips': | 
| igor@56 | 357             return "sudo xm console "+self.name | 
| igor@56 | 358         elif self.name in real_bridges or self.name in real_nodes: | 
| igor@56 | 359             return "echo Press enter to connect; read line; "+connection_table[self.name] | 
| igor@56 | 360 | 
| igor@56 | 361 | 
| igor@56 | 362 class Link: | 
| igor@56 | 363     def __init__ (self,name,node,interface,bridge,label=""): | 
| igor@56 | 364         self.name=name | 
| igor@56 | 365         self.node=node | 
| igor@56 | 366         self.interface=interface | 
| igor@56 | 367         self.bridge=bridge | 
| igor@56 | 368         self.label=label | 
| igor@56 | 369 | 
| igor@56 | 370     def is_temporary(self): | 
| igor@56 | 371         return [self.node,self.interface,self.bridge] in temporary_links | 
| igor@56 | 372 | 
| igor@56 | 373     def is_broken(self): | 
| igor@56 | 374         return ([self.node,self.interface,self.bridge] in broken_links) | 
| igor@56 | 375 | 
| igor@56 | 376     def graphviz_string(self): | 
| igor@56 | 377         if self.is_temporary(): | 
| igor@56 | 378             return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",color=blue,len=10,w=5,weight=5]" | 
| igor@56 | 379         if self.is_broken(): | 
| igor@56 | 380             return self.node+" -- "+self.bridge+" [taillabel=\"fa"+str(self.interface)+"/0\",style=dashed]" | 
| igor@56 | 381 | 
| igor@56 | 382         ip="\\n.%s.%s" % (bridges.index(self.bridge)+1, domains.index(self.node)+1) | 
| igor@56 | 383         if domain_types[domains.index(self.node)] == 'xenomips': | 
| igor@56 | 384             int_name="fa"+str(self.interface)+"/0" | 
| igor@56 | 385         else: | 
| igor@56 | 386             int_name="eth"+str(self.interface) | 
| igor@56 | 387         if self.label != "": | 
| igor@56 | 388             int_name = self.label | 
| igor@56 | 389         return self.node+" -- "+self.bridge+" [taillabel=\""+int_name+ip+"\",fontsize=14,fontname=fixed]" | 
| igor@56 | 390 | 
| igor@38 | 391 | 
| igor@23 | 392 #----------------------------------------------------------------------- | 
| igor@23 | 393 # DOMAINS | 
| igor@23 | 394 | 
| igor@23 | 395 def get_domain_id(domain): | 
| igor@23 | 396     return run_command_return_stdout("sudo xm list | awk '{if ($1 == \"'%s'\") print $2}'" % domain).rstrip("\n") | 
| igor@23 | 397 | 
| igor@22 | 398 | 
| igor@22 | 399 #----------------------------------------------------------------------- | 
| igor@22 | 400 # BRIDGES and IFACES | 
| igor@22 | 401 | 
| igor@22 | 402 def bridge_down(bridge): | 
| igor@22 | 403     """ | 
| igor@22 | 404     Turn the bridge <bridge> down | 
| igor@22 | 405     """ | 
| igor@38 | 406     if bridge in real_bridges: | 
| igor@38 | 407         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 408         return -1 | 
| igor@29 | 409     if bridge in bridges_turned_down: | 
| igor@29 | 410         print "Bridge %s is turned down already" % (bridge) | 
| igor@29 | 411     else: | 
| igor@29 | 412         bridges_turned_down.append(bridge) | 
| igor@29 | 413         run_command("sudo ip link set %s down" % bridge) | 
| igor@29 | 414         autoredraw() | 
| igor@22 | 415 | 
| igor@22 | 416 def bridge_up(bridge): | 
| igor@22 | 417     """ | 
| igor@22 | 418     Turn the bridge <bridge> up | 
| igor@22 | 419     """ | 
| igor@38 | 420     if bridge in real_bridges: | 
| igor@38 | 421         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 422         return -1 | 
| igor@29 | 423     if not (bridge in bridges_turned_down): | 
| igor@29 | 424         print "Bridge %s is turned up already" % (bridge) | 
| igor@29 | 425     else: | 
| igor@29 | 426         bridges_turned_down.remove(bridge) | 
| igor@29 | 427         run_command("sudo ip link set %s up" % bridge) | 
| igor@29 | 428         autoredraw() | 
| igor@22 | 429 | 
| igor@22 | 430 def show_bridge(bridge): | 
| igor@22 | 431     """ | 
| igor@22 | 432     Show the state of the bridge <bridge> | 
| igor@22 | 433     """ | 
| igor@38 | 434     if bridge in real_bridges: | 
| igor@38 | 435         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 436         return -1 | 
| igor@22 | 437     run_command("sudo ip link show %s" % bridge) | 
| igor@22 | 438 | 
| igor@23 | 439 | 
| igor@23 | 440 def int_disconnect(domain, int_number): | 
| igor@23 | 441     """ | 
| igor@23 | 442     Disconnect the interface with the number <int_number> | 
| igor@23 | 443     of the domain <domain> from the bridge to which | 
| igor@23 | 444     it is connected | 
| igor@23 | 445     """ | 
| igor@23 | 446     dom_id=get_domain_id(domain) | 
| igor@23 | 447     bridge=vbridges_table[domain][int_number] | 
| igor@23 | 448     if not bridge: | 
| igor@23 | 449         print "Interface %s of the %s domain is not connected" % (int_number, domain) | 
| igor@23 | 450         return 1 | 
| igor@23 | 451     run_command("sudo brctl delif %s vif%s.%s" % (bridge, dom_id, int_number)) | 
| igor@23 | 452     vbridges_table[domain][int_number]='' | 
| igor@28 | 453     if [ domain, int_number, bridge ] in temporary_links: | 
| igor@28 | 454         temporary_links.remove([ domain, int_number, bridge ]) | 
| igor@27 | 455     else: | 
| igor@28 | 456         broken_links.append([ domain, int_number, bridge ]) | 
| igor@27 | 457     autoredraw() | 
| igor@23 | 458 | 
| igor@23 | 459 def int_connect(domain, int_number, bridge): | 
| igor@23 | 460     """ | 
| igor@23 | 461     Connect the interface with the number <int_number> | 
| igor@24 | 462     of the domain <domain> to the bridge <bridge> | 
| igor@23 | 463     """ | 
| igor@38 | 464     if bridge in real_bridges: | 
| igor@38 | 465         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 466         return -1 | 
| igor@38 | 467 | 
| igor@23 | 468     dom_id=get_domain_id(domain) | 
| igor@23 | 469     if vbridges_table[domain][int_number]: | 
| igor@23 | 470         print "Interface %s of the %s domain is connected already to the %s bridge" % (int_number, domain, vbridges_table[domain][int_number]) | 
| igor@23 | 471         return 1 | 
| igor@23 | 472     run_command("sudo brctl addif %s vif%s.%s" % (bridge, dom_id, int_number)) | 
| igor@23 | 473     vbridges_table[domain][int_number]=bridge | 
| igor@28 | 474     if [ domain, int_number, bridge ] in broken_links: | 
| igor@28 | 475         broken_links.remove([ domain, int_number, bridge ]) | 
| igor@27 | 476     else: | 
| igor@28 | 477         temporary_links.append([ domain, int_number, bridge ]) | 
| igor@27 | 478     autoredraw() | 
| igor@23 | 479 | 
| igor@24 | 480 def int_reconnect(domain, int_number, bridge): | 
| igor@24 | 481     """ | 
| igor@24 | 482     Reconnect the interface with the number <int_number> | 
| igor@24 | 483     of the domain <domain> from the bridge to which | 
| igor@24 | 484     it is connected to the bridge <bridge> | 
| igor@24 | 485     """ | 
| igor@38 | 486     if bridge in real_bridges: | 
| igor@38 | 487         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 488         return -1 | 
| igor@38 | 489 | 
| igor@24 | 490     int_disconnect(domain, int_number) | 
| igor@24 | 491     int_connect(domain, int_number, bridge) | 
| igor@24 | 492 | 
| igor@24 | 493 def show_int(domain, int_number): | 
| igor@25 | 494     """ | 
| igor@25 | 495     Show information about the interface <int_nuber> | 
| igor@25 | 496     of the domain <domain> | 
| igor@25 | 497     """ | 
| igor@26 | 498     return vbridges_table[domain][int_number] | 
| igor@24 | 499 | 
| igor@28 | 500 | 
| igor@28 | 501 def dump_start(bridge, filter=""): | 
| igor@38 | 502     if bridge in real_bridges: | 
| igor@38 | 503         print "Bridge %s is a real bridge" % (bridge) | 
| igor@38 | 504         return -1 | 
| igor@32 | 505     try: | 
| igor@32 | 506         print "Writing dump... (press Ctrl-C to stop)" | 
| igor@32 | 507         run_command("sudo tcpdump -w xentaur.dump -i %s %s > /dev/null 2>&1 " % (bridge,filter)) | 
| igor@32 | 508     except: | 
| igor@32 | 509         print "Done.\n Dump is written to xentaur.dump" | 
| igor@28 | 510     return 0 | 
| igor@28 | 511 | 
| igor@28 | 512 def dump_stop(): | 
| igor@28 | 513     return 0 | 
| igor@33 | 514 | 
| igor@33 | 515 | 
| igor@33 | 516 #----------------------------------------------------------------------- | 
| igor@33 | 517 # CONFIGURATION TEMPLATES | 
| igor@33 | 518 | 
| igor@33 | 519 | 
| igor@33 | 520 def configure_ip_addresses(doms=domains): | 
| igor@40 | 521 | 
| igor@40 | 522     cisco_set_ip_on_int=""" | 
| igor@40 | 523 \n\n\n | 
| igor@40 | 524 int fa%s/0 | 
| igor@40 | 525 no ip address | 
| igor@40 | 526 ip address %s 255.255.255.0 | 
| igor@40 | 527 no shutdown | 
| igor@40 | 528 exit | 
| igor@40 | 529 """ | 
| igor@40 | 530 | 
| igor@40 | 531     quagga_set_ip_on_int=""" | 
| igor@40 | 532 int eth%s | 
| igor@40 | 533 no ip address | 
| igor@40 | 534 ip address %s/24 | 
| igor@40 | 535 no shutdown | 
| igor@40 | 536 exit | 
| igor@40 | 537 """ | 
| igor@40 | 538 | 
| igor@40 | 539     for dom in doms: | 
| igor@40 | 540         i=domains.index(dom)+1 | 
| igor@40 | 541         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@40 | 542             command = quagga_set_ip_on_int | 
| igor@40 | 543             write_to(i,"\nconf t\n") | 
| igor@40 | 544             j=0 | 
| igor@40 | 545             for br in  vbridges_table[dom]: | 
| igor@40 | 546                 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i))) | 
| igor@40 | 547                 j+=1 | 
| igor@40 | 548             write_to(i,"\nend\n") | 
| igor@40 | 549         else: | 
| igor@40 | 550             command = cisco_set_ip_on_int | 
| igor@40 | 551             write_to(i,"\nena\nconf t\n") | 
| igor@40 | 552             j=0 | 
| igor@40 | 553             for br in  vbridges_table[dom]: | 
| igor@40 | 554                 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i))) | 
| igor@40 | 555                 j+=1 | 
| igor@40 | 556             write_to(i,"\nend\n") | 
| igor@40 | 557     return 0 | 
| igor@40 | 558 | 
| igor@40 | 559 def configure_no_ip_addresses(doms=domains): | 
| igor@40 | 560 | 
| igor@40 | 561     cisco_set_ip_on_int=""" | 
| igor@40 | 562 \n\n\n | 
| igor@40 | 563 int fa%s/0 | 
| igor@40 | 564 no ip address %s 255.255.255.0 | 
| igor@40 | 565 exit | 
| igor@40 | 566 """ | 
| igor@40 | 567 | 
| igor@40 | 568     quagga_set_ip_on_int=""" | 
| igor@40 | 569 int eth%s | 
| igor@40 | 570 no ip address %s/24 | 
| igor@40 | 571 exit | 
| igor@40 | 572 """ | 
| igor@40 | 573 | 
| igor@40 | 574     for dom in doms: | 
| igor@40 | 575         i=domains.index(dom)+1 | 
| igor@40 | 576         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@40 | 577             command = quagga_set_ip_on_int | 
| igor@40 | 578             write_to(i,"\nconf t\n") | 
| igor@40 | 579             j=0 | 
| igor@40 | 580             for br in  vbridges_table[dom]: | 
| igor@40 | 581                 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i))) | 
| igor@40 | 582                 j+=1 | 
| igor@40 | 583             write_to(i,"\nend\n") | 
| igor@40 | 584         else: | 
| igor@40 | 585             command = cisco_set_ip_on_int | 
| igor@40 | 586             write_to(i,"\nena\nconf t\n") | 
| igor@40 | 587             j=0 | 
| igor@40 | 588             for br in  vbridges_table[dom]: | 
| igor@40 | 589                 write_to(i,command % (j, "192.168.%s.%s"%(bridges.index(br)+1,i))) | 
| igor@40 | 590                 j+=1 | 
| igor@40 | 591             write_to(i,"\nend\n") | 
| igor@33 | 592     return 0 | 
| igor@33 | 593 | 
| igor@33 | 594 def configure_ospf(doms=domains): | 
| igor@40 | 595     for dom in doms: | 
| igor@40 | 596         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@40 | 597             write_to(dom,"\n\nconf t\nrouter ospf\nnetwork 192.168.0.0/16 area 0\nend\n") | 
| igor@40 | 598         else: | 
| igor@40 | 599             write_to(dom,"\n\nena\nconf t\nrouter ospf 1\nnetwork 192.168.0.0 0.0.255.255 area 0\nend\n") | 
| igor@33 | 600     return 0 | 
| igor@33 | 601 | 
| igor@49 | 602 def configure_hostname(doms=domains): | 
| igor@49 | 603     for dom in doms: | 
| igor@49 | 604         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@49 | 605             write_to(dom,"\n\nconf t\nhostname %s\nend\n" % dom) | 
| igor@49 | 606         else: | 
| igor@49 | 607             write_to(dom,"\n\nena\nconf t\nhostname %s\nend\n" % dom) | 
| igor@49 | 608     return 0 | 
| igor@49 | 609 | 
| igor@49 | 610 def configure_logging_synchronous(doms=domains): | 
| igor@49 | 611     for dom in domains: | 
| igor@49 | 612         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@49 | 613             0 | 
| igor@49 | 614         else: | 
| igor@49 | 615             write_to(dom,"\n\nena\nconf t\nline console 0\nlogging synchronous\nend\n") | 
| igor@49 | 616     return 0 | 
| igor@49 | 617 | 
| igor@51 | 618 def configure_exec_timeout_0(doms=domains): | 
| igor@51 | 619     for dom in domains: | 
| igor@51 | 620         if domain_types[domains.index(dom)] == 'quagga': | 
| igor@51 | 621             0 | 
| igor@51 | 622         else: | 
| igor@52 | 623             write_to(dom,"\n\nena\nconf t\nline console 0\nexec-timeout 0\nend\n") | 
| igor@51 | 624     return 0 | 
| igor@51 | 625 | 
| igor@55 | 626 def configure_no_cdp_log_mismatch_duplex(doms=domains): | 
| igor@55 | 627     for dom in filter_by_type(domains,'xenomips'): | 
| igor@55 | 628         write_to(dom,"\n\nena\nconf t\nno cdp log mismatch duplex\nend\n") | 
| igor@55 | 629 | 
| igor@33 | 630 def configure_save(doms=domains): | 
| igor@33 | 631     write_to(doms,"\nwr\n") | 
| igor@33 | 632 | 
| igor@49 | 633 def configure_root(doms=domains): | 
| igor@49 | 634     write_to(doms,"root\n") | 
| igor@49 | 635 | 
| igor@0 | 636 #----------------------------------------------------------------------- | 
| igor@0 | 637 | 
| igor@0 | 638 | 
| igor@0 | 639 def add_domain(name,type): | 
| igor@0 | 640     domains.append(name) | 
| igor@0 | 641     domain_types.append(type) | 
| igor@0 | 642 | 
| igor@0 | 643 def brake_link(domain,bridge): | 
| igor@0 | 644     broken_links.append([domain,bridge]) | 
| igor@0 | 645 | 
| igor@4 | 646 wt_timeout=0.5 | 
| igor@8 | 647 def write_to(screen,string,return_to_screen=""): | 
| igor@2 | 648     """ | 
| igor@2 | 649     write_to(screen,string): | 
| igor@2 | 650 | 
| igor@8 | 651         Type *string* to the specified screen(s). | 
| igor@8 | 652         Screen may be specified with the number *screen*, | 
| igor@8 | 653         with array of numbers, | 
| igor@8 | 654         with array of names. | 
| igor@2 | 655 | 
| igor@2 | 656     """ | 
| igor@5 | 657     screen_numbers=[]           # number of the screens to write to | 
| igor@5 | 658     if type(screen) == list: | 
| igor@5 | 659         screen_numbers=map(lambda x: domains.index(x)+1, screen) | 
| igor@5 | 660     elif type(screen) == int: | 
| igor@5 | 661         screen_numbers=[screen] | 
| igor@5 | 662     else: | 
| igor@5 | 663         screen_numbers=[domains.index(screen)+1] | 
| igor@5 | 664 | 
| igor@5 | 665     for screen_number in screen_numbers: | 
| igor@5 | 666         run_command("screen -X select "+str(screen_number)) | 
| igor@5 | 667         time.sleep(wt_timeout) | 
| igor@5 | 668         for line in string.splitlines(): | 
| igor@5 | 669             f=open('/tmp/xentaurbuf', 'w') | 
| igor@5 | 670             f.write(line+"\n") | 
| igor@5 | 671             f.close() | 
| igor@5 | 672             run_command("screen -X readreg p /tmp/xentaurbuf") | 
| igor@5 | 673             time.sleep(wt_timeout) | 
| igor@5 | 674             run_command("nohup screen -X paste p >& /dev/null") | 
| igor@5 | 675             time.sleep(wt_timeout) | 
| igor@5 | 676 | 
| igor@8 | 677         if return_to_screen != "": | 
| igor@8 | 678             run_command("screen -X select %s" % (return_to_screen)) | 
| igor@8 | 679             time.sleep(wt_timeout) | 
| igor@0 | 680 | 
| igor@49 | 681 def filter_by_type(doms,type): | 
| igor@49 | 682     """ | 
| igor@49 | 683     filter_by_type(doms,type) | 
| igor@49 | 684 | 
| igor@49 | 685         Return only domains of *doms* that have specified *type* | 
| igor@49 | 686     """ | 
| igor@49 | 687     return filter(lambda x: domain_types[domains.index(x)]==type,domains) | 
| igor@49 | 688 | 
| igor@0 | 689 #----------------------------------------------------------------------- | 
| igor@0 | 690 | 
| igor@5 | 691 cisco_fa01_up=""" | 
| igor@5 | 692 ena | 
| igor@5 | 693 conf t | 
| igor@5 | 694 int fa0/0 | 
| igor@49 | 695 duplex half | 
| igor@5 | 696 no shutdown | 
| igor@5 | 697 exit | 
| igor@5 | 698 int fa1/0 | 
| igor@49 | 699 duplex half | 
| igor@5 | 700 no shutdown | 
| igor@5 | 701 exit | 
| igor@5 | 702 exit | 
| igor@5 | 703 exit | 
| igor@5 | 704 """ | 
| igor@5 | 705 | 
| igor@5 | 706 cisco_set_ip_on_int=""" | 
| igor@5 | 707 interface fa%s/0 | 
| igor@5 | 708 no ip address | 
| igor@5 | 709 ip address %s 255.255.255.0 | 
| igor@5 | 710 exit | 
| igor@5 | 711 """ | 
| igor@5 | 712 | 
| igor@0 | 713 nodes=domains | 
| igor@0 | 714 | 
| igor@56 | 715 create_objects() | 
| igor@56 | 716 | 
| igor@56 | 717 | 
| igor@49 | 718 if len(sys.argv) == 2: | 
| igor@49 | 719     if sys.argv[1] == 'start-all': | 
| igor@0 | 720         start_all() | 
| igor@49 | 721     elif sys.argv[1] == 'start-domains': | 
| igor@49 | 722         start_domains() | 
| igor@49 | 723     elif sys.argv[1] == 'start-bridges': | 
| igor@49 | 724         start_bridges() | 
| igor@49 | 725     elif sys.argv[1] == 'stop-all': | 
| igor@0 | 726         stop_all() | 
| igor@49 | 727     elif sys.argv[1] == 'stop-domains': | 
| igor@49 | 728         stop_domains() | 
| igor@49 | 729     elif sys.argv[1] == 'stop-bridges': | 
| igor@49 | 730         stop_bridges() | 
| igor@49 | 731     elif sys.argv[1] == 'restart-all': | 
| igor@49 | 732         restart_all() | 
| igor@0 | 733     elif sys.argv[1] == 'screen': | 
| igor@50 | 734         screen() | 
| igor@0 | 735     elif sys.argv[1] == 'graph': | 
| igor@0 | 736         graph() | 
| igor@0 | 737     elif sys.argv[1] == 'shell': | 
| igor@0 | 738         shell() | 
| igor@60 | 739     elif sys.argv[1] == 'info': | 
| igor@60 | 740         info() | 
| igor@49 | 741     else: | 
| igor@49 | 742         show_usage() | 
| igor@49 | 743         sys.exit(1) | 
| igor@49 | 744 elif len(sys.argv) == 3: | 
| igor@49 | 745     if sys.argv[1] == 'start': | 
| igor@49 | 746         start_domain(sys.argv[2]) | 
| igor@49 | 747     elif sys.argv[1] == 'stop': | 
| igor@49 | 748         stop_domain(sys.argv[2]) | 
| igor@49 | 749     elif sys.argv[1] == 'restart': | 
| igor@49 | 750         stop_domain(sys.argv[2]) | 
| igor@49 | 751         start_domain(sys.argv[2]) | 
| igor@49 | 752     else: | 
| igor@49 | 753         show_usage() | 
| igor@49 | 754         sys.exit(1) | 
| igor@0 | 755 else: | 
| igor@0 | 756     show_usage() | 
| igor@0 | 757     sys.exit(1) | 
| igor@0 | 758 | 
| igor@0 | 759 sys.exit(0) | 
| igor@0 | 760 | 
| igor@0 | 761 |