Changeset 0d830de
- Timestamp:
- Aug 27, 2008 7:24:55 PM (16 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-1.30, version-2.00, version-3.01, version-3.02
- Children:
- b234bb9
- Parents:
- 3441fe3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/fedd_create_experiment.py
r3441fe3 r0d830de 267 267 pid = tbparams[tb]['project'] 268 268 # XXX 269 base_confs = ( "hosts", "vtopo.xml", "viz.xml")269 base_confs = ( "hosts",) 270 270 tclfile = "%s.%s.tcl" % (eid, tb) 271 271 expinfo_exec = "/usr/testbed/bin/expinfo" … … 299 299 if m: state = "none" 300 300 rv = status.wait() 301 # No experiment returns a non-zero rv. If we successfully parsed a 302 # "none" outcome, ignore teh return code. 301 # If the experiment is not present the subcommand returns a non-zero 302 # return value. If we successfully parsed a "none" outcome, ignore the 303 # return code. 303 304 if rv != 0 and state != "none": 304 305 raise service_error(service_error.internal, … … 456 457 % (self.ssh_keygen, rv)) 457 458 458 def genviz(self, topo_file, viz_file): 459 def gentopo(self, str): 460 class topo_parse: 461 def __init__(self): 462 self.str_subelements = ('vname', 'vnode', 'ips', 'ip', 'member') 463 self.int_subelements = ( 'bandwidth',) 464 self.float_subelements = ( 'delay',) 465 self.nodes = [ ] 466 self.lans = [ ] 467 self.element = { } 468 self.topo = { \ 469 'nodes': { 'node': self.nodes },\ 470 'lans' : { 'lan' : self.lans },\ 471 } 472 self.chars = "" 473 474 def end_element(self, name): 475 if name == 'node': 476 self.nodes.append(self.element) 477 self.element = { } 478 elif name == 'lan': 479 self.lans.append(self.element) 480 self.element = { } 481 elif name in self.str_subelements: 482 self.element[name] = self.chars 483 self.chars = "" 484 elif name in self.int_subelements: 485 self.element[name] = int(self.chars) 486 self.chars = "" 487 elif name in self.float_subelements: 488 self.element[name] = float(self.chars) 489 self.chars = "" 490 491 def found_chars(self, data): 492 self.chars += data.rstrip() 493 494 495 tp = topo_parse(); 496 parser = xml.parsers.expat.ParserCreate() 497 parser.EndElementHandler = tp.end_element 498 parser.CharacterDataHandler = tp.found_chars 499 500 parser.Parse(str) 501 502 return tp.topo 503 504 505 def genviz(self, topo): 459 506 """ 460 Generate the visualization file from the topology file507 Generate the visualization the virtual topology 461 508 """ 462 463 class topo_parse:464 """465 Parse the vtopo file into a set of lans, links and nodes.466 """467 def __init__(self):468 self.links = {} # Each link is a list of at most 2 nodes469 self.lans = {} # Lans have more than 2 nodes470 self.nodes = {} # The nodes in the experiment471 self.lan = {} # The current link/len being collected472 self.in_lan = False # Is the conatining element lan?473 self.in_node = False # Is the conatining element node?474 self.chars = None # Last set of marked-up chars475 476 def start_element(self, name, attrs):477 """478 New element started. Set flags and clear lan479 """480 if name == "node":481 self.in_node = True482 elif name == "lan":483 self.in_lan = True484 self.lan.clear()485 486 def end_element(self, name):487 """488 End of element. Collect data if appropriate489 490 If a node or lan is ending, create an entry in nodes or491 lans/links. If a vname/vnode in a node or lan is ending,492 capture its name. If a lan is ending, add the node to the493 evolving link or lan.494 """495 if name == "node":496 self.in_node = False497 if self.in_node and name == "vname":498 self.nodes[self.chars] = "node"499 if self.in_lan:500 if name != "lan":501 if name == 'vname' or name == 'vnode':502 self.lan[name] = self.chars503 else:504 self.in_lan = False505 vname = self.lan['vname']506 links = self.links.get(vname, [])507 if len(links) == 2:508 # This link needs to be a lan instead509 self.nodes[vname] = "lan"510 self.lans[vname] = \511 [ l for l in links, self.lan['vnode'] ]512 del self.links[vname]513 self.lan = {}514 return515 lans = self.lans.get(vname, [])516 if len(lans) > 0:517 lans.append(self.lan['vnode'])518 self.lan = {}519 return520 if not vname in self.links:521 self.links[vname] = []522 self.links[vname].append(self.lan['vnode'])523 self.lan = {}524 return525 526 def found_chars(self, data):527 """528 Capture marked up chars for later529 """530 self.chars = data531 509 532 510 neato = "/usr/local/bin/neato" … … 535 513 vis_re = re.compile('^\s*"?([\w\-]+)"?\s+\[.*pos="(\d+),(\d+)"') 536 514 vis_fmt = "<node><name>%s</name><x>%s</x><y>%s</y><type>" + \ 537 "%s</type></node>" 515 "%s</type></node>" 516 517 try: 518 # Node names 519 nodes = [ n['vname'] for n in topo['nodes']['node'] ] 520 topo_lans = topo['lans']['lan'] 521 except KeyError: 522 raise service_error(service_error.internal, "Bad topology") 523 524 lans = { } 525 links = { } 526 527 # Walk through the virtual topology, organizing the connections into 528 # 2-node connections (links) and more-than-2-node connections (lans). 529 # When a lan is created, it's added to the list of nodes (there's a 530 # node in the visualization for the lan). 531 for l in topo_lans: 532 if links.has_key(l['vname']): 533 if len(links[l['vname']]) < 2: 534 links[l['vname']].append(l['vnode']) 535 else: 536 nodes.append(l['vname']) 537 lans[l['vname']] = links[l['vname']] 538 del links[l['vname']] 539 lans[l['vname']].append(l['vnode']) 540 elif lans.has_key(l['vname']): 541 lans[l['vname']].append(l['vnode']) 542 else: 543 links[l['vname']] = [ l['vnode'] ] 544 545 546 # Open up a temporary file for dot to turn into a visualization 538 547 try: 539 548 df, dotname = tempfile.mkstemp() 540 549 dotfile = os.fdopen(df, 'w') 541 infile = open(topo_file, 'r')542 out = open(viz_file, "w")543 550 except IOError: 544 551 raise service_error(service_error.internal, 545 552 "Failed to open file in genviz") 546 553 547 # Parse the topology file using XML tools548 tp = topo_parse();549 parser = xml.parsers.expat.ParserCreate()550 parser.StartElementHandler = tp.start_element551 parser.EndElementHandler = tp.end_element552 parser.CharacterDataHandler = tp.found_chars553 554 parser.ParseFile(infile)555 556 554 # Generate a dot/neato input file from the links, nodes and lans 557 555 try: 558 556 print >>dotfile, "graph G {" 559 for n in tp.nodes.keys():557 for n in nodes: 560 558 print >>dotfile, '\t"%s"' % n 561 for l in tp.links.keys():562 print >>dotfile, " -- ".join(tp.links[l])563 for l in tp.lans.keys():564 for n in tp.lans[l]:559 for l in links.keys(): 560 print >>dotfile, '\t"%s" -- "%s"' % tuple(links[l]) 561 for l in lans.keys(): 562 for n in lans[l]: 565 563 print >>dotfile, '\t "%s" -- "%s"' % (n,l) 566 564 print >>dotfile, "}" 567 565 dotfile.close() 566 except TypeError: 567 raise service_error(service_error.internal, 568 "Single endpoint link in vtopo") 568 569 except IOError: 569 570 raise service_error(service_error.internal, "Cannot write dot file") … … 573 574 '-Gpack=true', dotname], stdout=PIPE) 574 575 575 # Translate dot to emulab format 576 try: 577 print >>out, "<vis>" 578 for line in dot.stdout: 579 m = vis_re.match(line) 580 if m: 581 n, x, y = (m.group(1), m.group(2), m.group(3)) 582 if tp.nodes.has_key(n): 583 print >>out, vis_fmt % (n, x, y, tp.nodes[n]) 584 print >>out, "</vis>" 585 out.close() 586 except IOError: 587 raise service_error(service_error.internal, 588 "Failed to write visualization file") 576 # Translate dot to vis format 577 vis_nodes = [ ] 578 vis = { 'node': vis_nodes } 579 for line in dot.stdout: 580 m = vis_re.match(line) 581 if m: 582 vn = m.group(1) 583 vis_node = {'name': vn, \ 584 'x': int(m.group(2)),\ 585 'y' : int(m.group(3)),\ 586 } 587 if vn in links.keys() or vn in lans.keys(): 588 vis_node['type'] = 'lan' 589 else: 590 vis_node['type'] = 'node' 591 vis_nodes.append(vis_node) 589 592 rv = dot.wait() 593 590 594 os.remove(dotname) 591 return rv == 0 595 if rv == 0 : return vis 596 else: return None 592 597 593 598 … … 1035 1040 return True 1036 1041 1042 class shunt_to_string: 1043 def __init__(self, begin, end): 1044 self.begin = re.compile(begin) 1045 self.end = re.compile(end) 1046 self.in_shunt = False 1047 self.str = "" 1048 1049 def __call__(self, line): 1050 if not self.in_shunt: 1051 if self.begin.match(line): 1052 self.in_shunt = True 1053 return True 1054 else: 1055 return False 1056 else: 1057 if self.end.match(line): 1058 self.in_shunt = False 1059 else: 1060 self.str += line 1061 return True 1062 1037 1063 def create_experiment(self, req, fid): 1038 1064 try: … … 1102 1128 parse_gateways = self.gateways(eid, master, tmpdir, 1103 1129 gw_pubkey_base, gw_secretkey_base, self.copy_file) 1104 parse_vtopo = self.shunt_to_ file("^#\s+Begin\s+Vtopo",1105 "^#\s+End\s+Vtopo" , tmpdir + "/vtopo.xml")1130 parse_vtopo = self.shunt_to_string("^#\s+Begin\s+Vtopo", 1131 "^#\s+End\s+Vtopo") 1106 1132 parse_hostnames = self.shunt_to_file("^#\s+Begin\s+hostnames", 1107 1133 "^#\s+End\s+hostnames", tmpdir + "/hosts") … … 1131 1157 "Bad tcl parse? %s" % line) 1132 1158 1133 self.genviz(tmpdir + "/vtopo.xml", tmpdir + "/viz.xml") 1159 vtopo = self.gentopo(parse_vtopo.str) 1160 if not vtopo: 1161 raise service_error(service_error.internal, 1162 "Failed to generate virtual topology") 1163 1164 vis = self.genviz(vtopo) 1165 if not vis: 1166 raise service_error(service_error.internal, 1167 "Failed to generate visualization") 1134 1168 1135 1169 # Copy tarfiles and rpms needed at remote sites into a staging area … … 1200 1234 return { 'emulab' : [ tbparams[tb]['emulab'] \ 1201 1235 for tb in tbparams.keys() \ 1202 if tbparams[tb].has_key('emulab') ] } 1236 if tbparams[tb].has_key('emulab') ],\ 1237 'experiment': vtopo,\ 1238 'vis' : vis } 1203 1239 1204 1240 if __name__ == '__main__':
Note: See TracChangeset
for help on using the changeset viewer.