Changeset 895a133
- Timestamp:
- Sep 8, 2009 2:33:33 PM (15 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-2.00, version-3.01, version-3.02
- Children:
- 574055e
- Parents:
- e794984
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/federation/experiment_control.py
re794984 r895a133 1097 1097 1098 1098 1099 def create_experiment(self, req, fid): 1100 """ 1101 The external interface to experiment creation called from the 1102 dispatcher. 1103 1104 Creates a working directory, splits the incoming description using the 1105 splitter script and parses out the avrious subsections using the 1106 lcasses above. Once each sub-experiment is created, use pooled threads 1107 to instantiate them and start it all up. 1108 """ 1109 1110 def add_kit(e, kit): 1111 """ 1112 Add a Software object created from the list of (install, location) 1113 tuples passed as kit to the software attribute of an object e. We 1114 do this enough to break out the code, but it's kind of a hack to 1115 avoid changing the old tuple rep. 1116 """ 1117 1118 s = [ topdl.Software(install=i, location=l) for i, l in kit] 1119 1120 if isinstance(e.software, list): e.software.extend(s) 1121 else: e.software = s 1122 1123 1124 if not self.auth.check_attribute(fid, 'create'): 1125 raise service_error(service_error.access, "Create access denied") 1126 1127 try: 1128 tmpdir = tempfile.mkdtemp(prefix="split-") 1129 except IOError: 1130 raise service_error(service_error.internal, "Cannot create tmp dir") 1131 1132 gw_pubkey_base = "fed.%s.pub" % self.ssh_type 1133 gw_secretkey_base = "fed.%s" % self.ssh_type 1134 gw_pubkey = tmpdir + "/keys/" + gw_pubkey_base 1135 gw_secretkey = tmpdir + "/keys/" + gw_secretkey_base 1136 tclfile = tmpdir + "/experiment.tcl" 1137 tbparams = { } 1138 try: 1139 access_user = self.accessdb[fid] 1140 except KeyError: 1141 raise service_error(service_error.internal, 1142 "Access map and authorizer out of sync in " + \ 1143 "create_experiment for fedid %s" % fid) 1144 1145 pid = "dummy" 1146 gid = "dummy" 1147 try: 1148 os.mkdir(tmpdir+"/keys") 1149 except OSError: 1150 raise service_error(service_error.internal, 1151 "Can't make temporary dir") 1152 1153 req = req.get('CreateRequestBody', None) 1154 if not req: 1155 raise service_error(service_error.req, 1156 "Bad request format (no CreateRequestBody)") 1157 # The tcl parser needs to read a file so put the content into that file 1158 descr=req.get('experimentdescription', None) 1159 if descr: 1160 file_content=descr.get('ns2description', None) 1161 if file_content: 1162 try: 1163 f = open(tclfile, 'w') 1164 f.write(file_content) 1165 f.close() 1166 except IOError: 1167 raise service_error(service_error.internal, 1168 "Cannot write temp experiment description") 1169 else: 1170 raise service_error(service_error.req, 1171 "Only ns2descriptions supported") 1172 else: 1173 raise service_error(service_error.req, "No experiment description") 1174 1175 # Generate an ID for the experiment (slice) and a certificate that the 1176 # allocator can use to prove they own it. We'll ship it back through 1177 # the encrypted connection. 1178 (expid, expcert) = generate_fedid("test", dir=tmpdir, log=self.log) 1099 def add_kit(self, e, kit): 1100 """ 1101 Add a Software object created from the list of (install, location) 1102 tuples passed as kit to the software attribute of an object e. We 1103 do this enough to break out the code, but it's kind of a hack to 1104 avoid changing the old tuple rep. 1105 """ 1106 1107 s = [ topdl.Software(install=i, location=l) for i, l in kit] 1108 1109 if isinstance(e.software, list): e.software.extend(s) 1110 else: e.software = s 1111 1112 1113 def create_experiment_state(self, fid, req, expid, expcert): 1114 """ 1115 Create the initial entry in the experiment's state. The expid and 1116 expcert are the experiment's fedid and certifacte that represents that 1117 ID, which are installed in the experiment state. If the request 1118 includes a suggested local name that is used if possible. If the local 1119 name is already taken by an experiment owned by this user that has 1120 failed, it is overwriutten. Otherwise new letters are added until a 1121 valid localname is found. The generated local name is returned. 1122 """ 1179 1123 1180 1124 if req.has_key('experimentID') and \ … … 1233 1177 self.state_lock.release() 1234 1178 1179 return eid 1180 1181 1182 def allocate_ips_to_topo(self, top): 1183 """ 1184 Add an ip4_address attribute to all the hosts in teh topology, based on 1185 the shared substrates on which they sit. An /etc/hosts file is also 1186 created and returned as a list of hostfiles entries. 1187 """ 1188 subs = sorted(top.substrates, 1189 cmp=lambda x,y: cmp(len(x.interfaces), len(y.interfaces)), 1190 reverse=True) 1191 ips = ip_allocator(int(ip_addr("10.0.0.0")), 2 **24) 1192 ifs = { } 1193 hosts = [ ] 1194 1195 for idx, s in enumerate(subs): 1196 a = ips.allocate(len(s.interfaces)+2) 1197 if a : 1198 base, num = a 1199 if num < len(s.interfaces) +2 : 1200 raise service_error(service_error.internal, 1201 "Allocator returned wrong number of IPs??") 1202 else: 1203 raise service_error(service_error.req, 1204 "Cannot allocate IP addresses") 1205 1206 base += 1 1207 for i in s.interfaces: 1208 i.attribute.append( 1209 topdl.Attribute('ip4_address', 1210 "%s" % ip_addr(base))) 1211 hname = i.element.name[0] 1212 if ifs.has_key(hname): 1213 hosts.append("%s\t%s-%s %s-%d" % \ 1214 (ip_addr(base), hname, s.name, hname, 1215 ifs[hname])) 1216 else: 1217 ifs[hname] = 0 1218 hosts.append("%s\t%s-%s %s-%d %s" % \ 1219 (ip_addr(base), hname, s.name, hname, 1220 ifs[hname], hname)) 1221 1222 ifs[hname] += 1 1223 base += 1 1224 return hosts 1225 1226 def get_access_to_testbeds(self, testbeds, user, access_user, 1227 export_project, master, allocated, tbparams): 1228 """ 1229 Request access to the various testbeds required for this instantiation 1230 (passed in as testbeds). User, access_user, expoert_project and master 1231 are used to construct the correct requests. Per-testbed parameters are 1232 returned in tbparams. 1233 """ 1234 for tb in testbeds: 1235 self.get_access(tb, None, user, tbparams, master, 1236 export_project, access_user) 1237 allocated[tb] = 1 1238 1239 def split_topology(self, top, topo, testbeds, eid, master, tbparams): 1240 """ 1241 Create the sub-topologies that are needed for experimetn instantiation. 1242 Along the way attach startup commands to the computers in the 1243 subtopologies. 1244 """ 1245 for tb in testbeds: 1246 topo[tb] = top.clone() 1247 to_delete = [ ] 1248 for e in topo[tb].elements: 1249 etb = e.get_attribute('testbed') 1250 if etb and etb != tb: 1251 for i in e.interface: 1252 for s in i.subs: 1253 try: 1254 s.interfaces.remove(i) 1255 except ValueError: 1256 raise service_error(service_error.internal, 1257 "Can't remove interface??") 1258 to_delete.append(e) 1259 for e in to_delete: 1260 topo[tb].elements.remove(e) 1261 topo[tb].make_indices() 1262 1263 for e in [ e for e in topo[tb].elements \ 1264 if isinstance(e,topdl.Computer)]: 1265 if tb == master: 1266 cmd = 'sudo -H /usr/local/federation/bin/make_hosts /proj/%s/exp/%s/tmp/hosts >& /tmp/federate' % (tbparams[tb].get('project', 'project'), eid) 1267 else: 1268 cmd = "sudo -H /bin/sh /usr/local/federation/bin/federate.sh >& /tmp/federate" 1269 scmd = e.get_attribute('startup') 1270 if scmd: 1271 cmd = "%s \\$USER '%s'" % (cmd, scmd) 1272 1273 e.set_attribute('startup', cmd) 1274 if self.fedkit: self.add_kit(e, self.fedkit) 1275 1276 def add_portals(self, top, topo, eid, master, tbparams): 1277 """ 1278 For each substrate in the main topology, find those that 1279 have nodes on more than one testbed. Insert portal nodes 1280 into the copies of those substrates on the sub topologies. 1281 """ 1282 for s in top.substrates: 1283 # tbs will contain an ip address on this subsrate that is in 1284 # each testbed. 1285 tbs = { } 1286 for i in s.interfaces: 1287 e = i.element 1288 tb = e.get_attribute('testbed') 1289 if tb and not tbs.has_key(tb): 1290 for i in e.interface: 1291 if s in i.subs: 1292 tbs[tb]= i.get_attribute('ip4_address') 1293 if len(tbs) < 2: 1294 continue 1295 1296 # More than one testbed is on this substrate. Insert 1297 # some portals into the subtopologies. st == source testbed, 1298 # dt == destination testbed. 1299 segment_substrate = { } 1300 for st in tbs.keys(): 1301 segment_substrate[st] = { } 1302 for dt in [ t for t in tbs.keys() if t != st]: 1303 myname = "%stunnel" % dt 1304 desthost = "%stunnel" % st 1305 sproject = tbparams[st].get('project', 'project') 1306 dproject = tbparams[dt].get('project', 'project') 1307 mproject = tbparams[master].get('project', 'project') 1308 sdomain = tbparams[st].get('domain', ".example.com") 1309 ddomain = tbparams[dt].get('domain', ".example.com") 1310 mdomain = tbparams[master].get('domain', '.example.com') 1311 muser = tbparams[master].get('user', 'root') 1312 smbshare = tbparams[master].get('smbshare', 'USERS') 1313 # XXX: active and type need to be unkludged 1314 active = ("%s" % (st == master)) 1315 if not segment_substrate[st].has_key(dt): 1316 # Put a substrate and a segment for the connected 1317 # testbed in there. 1318 tsubstrate = \ 1319 topdl.Substrate(name='%s-%s' % (st, dt), 1320 attribute= [ 1321 topdl.Attribute( 1322 attribute='portal', 1323 value='true') 1324 ] 1325 ) 1326 segment_element = topdl.Segment( 1327 id= tbparams[dt]['allocID'], 1328 type='emulab', 1329 uri = self.tbmap.get(dt, None), 1330 interface=[ 1331 topdl.Interface( 1332 substrate=tsubstrate.name), 1333 ], 1334 attribute = [ 1335 topdl.Attribute(attribute=n, value=v) 1336 for n, v in (\ 1337 ('domain', ddomain), 1338 ('experiment', "%s/%s" % \ 1339 (dproject, eid)),) 1340 ], 1341 ) 1342 segment_substrate[st][dt] = tsubstrate 1343 topo[st].substrates.append(tsubstrate) 1344 topo[st].elements.append(segment_element) 1345 portal = topdl.Computer( 1346 name="%stunnel" % dt, 1347 attribute=[ 1348 topdl.Attribute(attribute=n,value=v) 1349 for n, v in (\ 1350 ('portal', 'true'), 1351 ('domain', sdomain), 1352 ('masterdomain', mdomain), 1353 ('masterexperiment', "%s/%s" % \ 1354 (mproject, eid)), 1355 ('masteruser', muser), 1356 ('smbshare', smbshare), 1357 ('experiment', "%s/%s" % \ 1358 (sproject, eid)), 1359 ('peer', "%s" % desthost), 1360 ('peer_segment', "%s" % \ 1361 tbparams[dt]['allocID']['fedid']), 1362 ('scriptdir', 1363 "/usr/local/federation/bin"), 1364 ('active', "%s" % active), 1365 ('portal_type', 'both'), 1366 ('startup', 'sudo -H /usr/local/federation/bin/fed-tun.pl -f /proj/%s/exp/%s/tmp/%s.%s.%s%s.gw.conf >& /tmp/bridge.log' % (sproject, eid, myname.lower(), eid.lower(), sproject.lower(), sdomain.lower()))) 1367 ], 1368 interface=[ 1369 topdl.Interface( 1370 substrate=s.name, 1371 attribute=[ 1372 topdl.Attribute( 1373 attribute='ip4_address', 1374 value=tbs[dt] 1375 ) 1376 ]), 1377 topdl.Interface( 1378 substrate=\ 1379 segment_substrate[st][dt].name, 1380 attribute=[ 1381 topdl.Attribute(attribute='portal', 1382 value='true') 1383 ] 1384 ), 1385 ], 1386 ) 1387 if self.fedkit: self.add_kit(portal, self.fedkit) 1388 if self.gatewaykit: self.add_kit(portal, self.gatewaykit) 1389 1390 topo[st].elements.append(portal) 1391 1392 # Connect the gateway nodes into the topologies and clear out 1393 # substrates that are not in the topologies 1394 for tb in tbparams.keys(): 1395 topo[tb].incorporate_elements() 1396 topo[tb].substrates = \ 1397 [s for s in topo[tb].substrates \ 1398 if len(s.interfaces) >0] 1399 1400 def wrangle_software(self, expid, top, topo, tbparams): 1401 """ 1402 Copy software out to the repository directory, allocate permissions and 1403 rewrite the segment topologies to look for the software in local 1404 places. 1405 """ 1406 1407 # Copy the rpms and tarfiles to a distribution directory from 1408 # which the federants can retrieve them 1409 linkpath = "%s/software" % expid 1410 softdir ="%s/%s" % ( self.repodir, linkpath) 1411 softmap = { } 1412 # These are in a list of tuples format (each kit). This comprehension 1413 # unwraps them into a single list of tuples that initilaizes the set of 1414 # tuples. 1415 pkgs = set([ t for l in [self.fedkit, self.gatewaykit] \ 1416 for p, t in l ]) 1417 pkgs.update([x.location for e in top.elements \ 1418 for x in e.software]) 1419 try: 1420 os.makedirs(softdir) 1421 except IOError, e: 1422 raise service_error( 1423 "Cannot create software directory: %s" % e) 1424 # The actual copying. Everything's converted into a url for copying. 1425 for pkg in pkgs: 1426 loc = pkg 1427 1428 scheme, host, path = urlparse(loc)[0:3] 1429 dest = os.path.basename(path) 1430 if not scheme: 1431 if not loc.startswith('/'): 1432 loc = "/%s" % loc 1433 loc = "file://%s" %loc 1434 try: 1435 u = urlopen(loc) 1436 except Exception, e: 1437 raise service_error(service_error.req, 1438 "Cannot open %s: %s" % (loc, e)) 1439 try: 1440 f = open("%s/%s" % (softdir, dest) , "w") 1441 self.log.debug("Writing %s/%s" % (softdir,dest) ) 1442 data = u.read(4096) 1443 while data: 1444 f.write(data) 1445 data = u.read(4096) 1446 f.close() 1447 u.close() 1448 except Exception, e: 1449 raise service_error(service_error.internal, 1450 "Could not copy %s: %s" % (loc, e)) 1451 path = re.sub("/tmp", "", linkpath) 1452 # XXX 1453 softmap[pkg] = \ 1454 "https://users.isi.deterlab.net:23232/%s/%s" %\ 1455 ( path, dest) 1456 1457 # Allow the individual segments to access the software. 1458 for tb in tbparams.keys(): 1459 self.auth.set_attribute(tbparams[tb]['allocID']['fedid'], 1460 "/%s/%s" % ( path, dest)) 1461 1462 # Convert the software locations in the segments into the local 1463 # copies on this host 1464 for soft in [ s for tb in topo.values() \ 1465 for e in tb.elements \ 1466 if getattr(e, 'software', False) \ 1467 for s in e.software ]: 1468 if softmap.has_key(soft.location): 1469 soft.location = softmap[soft.location] 1470 1471 1472 def create_experiment(self, req, fid): 1473 """ 1474 The external interface to experiment creation called from the 1475 dispatcher. 1476 1477 Creates a working directory, splits the incoming description using the 1478 splitter script and parses out the avrious subsections using the 1479 lcasses above. Once each sub-experiment is created, use pooled threads 1480 to instantiate them and start it all up. 1481 """ 1482 if not self.auth.check_attribute(fid, 'create'): 1483 raise service_error(service_error.access, "Create access denied") 1484 1485 try: 1486 tmpdir = tempfile.mkdtemp(prefix="split-") 1487 os.mkdir(tmpdir+"/keys") 1488 except IOError: 1489 raise service_error(service_error.internal, "Cannot create tmp dir") 1490 1491 gw_pubkey_base = "fed.%s.pub" % self.ssh_type 1492 gw_secretkey_base = "fed.%s" % self.ssh_type 1493 gw_pubkey = tmpdir + "/keys/" + gw_pubkey_base 1494 gw_secretkey = tmpdir + "/keys/" + gw_secretkey_base 1495 tclfile = tmpdir + "/experiment.tcl" 1496 tbparams = { } 1497 try: 1498 access_user = self.accessdb[fid] 1499 except KeyError: 1500 raise service_error(service_error.internal, 1501 "Access map and authorizer out of sync in " + \ 1502 "create_experiment for fedid %s" % fid) 1503 1504 pid = "dummy" 1505 gid = "dummy" 1506 1507 req = req.get('CreateRequestBody', None) 1508 if not req: 1509 raise service_error(service_error.req, 1510 "Bad request format (no CreateRequestBody)") 1511 # The tcl parser needs to read a file so put the content into that file 1512 descr=req.get('experimentdescription', None) 1513 if descr: 1514 file_content=descr.get('ns2description', None) 1515 if file_content: 1516 try: 1517 f = open(tclfile, 'w') 1518 f.write(file_content) 1519 f.close() 1520 except IOError: 1521 raise service_error(service_error.internal, 1522 "Cannot write temp experiment description") 1523 else: 1524 raise service_error(service_error.req, 1525 "Only ns2descriptions supported") 1526 else: 1527 raise service_error(service_error.req, "No experiment description") 1528 1529 # Generate an ID for the experiment (slice) and a certificate that the 1530 # allocator can use to prove they own it. We'll ship it back through 1531 # the encrypted connection. 1532 (expid, expcert) = generate_fedid("test", dir=tmpdir, log=self.log) 1533 1534 eid = self.create_experiment_state(fid, req, expid, expcert) 1235 1535 try: 1236 1536 # This catches exceptions to clear the placeholder if necessary … … 1252 1552 if not export_project: 1253 1553 raise service_error(service_error.req, "No export project") 1254 1554 1555 # Translate to topdl 1255 1556 if self.splitter_url: 1557 # XXX: need remote topdl translator 1256 1558 self.log.debug("Calling remote splitter at %s" % \ 1257 1559 self.splitter_url) … … 1279 1581 split_data = tclparser.stdout 1280 1582 1583 top = topdl.topology_from_xml(file=split_data, top="experiment") 1584 1585 hosts = self.allocate_ips_to_topo(top) 1586 # Find the testbeds to look up 1587 testbeds = set([ a.value for e in top.elements \ 1588 for a in e.attribute \ 1589 if a.attribute == 'testbed'] ) 1590 1281 1591 allocated = { } # Testbeds we can access 1282 # Allocate IP addresses: The allocator is a buddy system memory 1283 # allocator. Allocate from the largest substrate to the 1284 # smallest to make the packing more likely to work - i.e. 1285 # avoiding internal fragmentation. 1286 top = topdl.topology_from_xml(file=split_data, top="experiment") 1287 subs = sorted(top.substrates, 1288 cmp=lambda x,y: cmp(len(x.interfaces), 1289 len(y.interfaces)), 1290 reverse=True) 1291 ips = ip_allocator(int(ip_addr("10.0.0.0")), 2 **24) 1292 ifs = { } 1293 hosts = [ ] 1592 topo ={ } # Sub topologies 1593 self.get_access_to_testbeds(testbeds, user, access_user, 1594 export_project, master, allocated, tbparams) 1595 self.split_topology(top, topo, testbeds, eid, master, tbparams) 1596 1597 # Copy configuration files into the remote file store 1294 1598 # The config urlpath 1295 1599 configpath = "/%s/config" % expid 1296 1600 # The config file system location 1297 1601 configdir ="%s%s" % ( self.repodir, configpath) 1298 1299 for idx, s in enumerate(subs):1300 a = ips.allocate(len(s.interfaces)+2)1301 if a :1302 base, num = a1303 if num < len(s.interfaces) +2 :1304 raise service_error(service_error.internal,1305 "Allocator returned wrong number of IPs??")1306 else:1307 raise service_error(service_error.req,1308 "Cannot allocate IP addresses")1309 1310 base += 11311 for i in s.interfaces:1312 i.attribute.append(1313 topdl.Attribute('ip4_address',1314 "%s" % ip_addr(base)))1315 hname = i.element.name[0]1316 if ifs.has_key(hname):1317 hosts.append("%s\t%s-%s %s-%d" % \1318 (ip_addr(base), hname, s.name, hname,1319 ifs[hname]))1320 else:1321 ifs[hname] = 01322 hosts.append("%s\t%s-%s %s-%d %s" % \1323 (ip_addr(base), hname, s.name, hname,1324 ifs[hname], hname))1325 1326 ifs[hname] += 11327 base += 11328 # save config files1329 1602 try: 1330 1603 os.makedirs(configdir) … … 1332 1605 raise service_error( 1333 1606 "Cannot create config directory: %s" % e) 1334 # Find the testbeds to look up1335 testbeds = set([ a.value for e in top.elements \1336 for a in e.attribute \1337 if a.attribute == 'testbed'] )1338 1339 1340 # Make per testbed topologies. Copy the main topo and remove1341 # interfaces and nodes that don't live in the testbed.1342 topo ={ }1343 for tb in testbeds:1344 self.get_access(tb, None, user, tbparams, master,1345 export_project, access_user)1346 allocated[tb] = 11347 topo[tb] = top.clone()1348 to_delete = [ ]1349 for e in topo[tb].elements:1350 etb = e.get_attribute('testbed')1351 if etb and etb != tb:1352 for i in e.interface:1353 for s in i.subs:1354 try:1355 s.interfaces.remove(i)1356 except ValueError:1357 raise service_error(service_error.internal,1358 "Can't remove interface??")1359 to_delete.append(e)1360 for e in to_delete:1361 topo[tb].elements.remove(e)1362 topo[tb].make_indices()1363 1364 for e in topo[tb].elements:1365 if tb == master:1366 cmd = 'sudo -H /usr/local/federation/bin/make_hosts /proj/%s/exp/%s/tmp/hosts >& /tmp/federate' % (tbparams[tb].get('project', 'project'), eid)1367 else:1368 cmd = "sudo -H /bin/sh /usr/local/federation/bin/federate.sh >& /tmp/federate"1369 scmd = e.get_attribute('startup')1370 if scmd:1371 cmd = "%s \\$USER '%s'" % (cmd, scmd)1372 1373 e.set_attribute('startup', cmd)1374 if self.fedkit: add_kit(e, self.fedkit)1375 1376 # Copy configuration files into the remote file store1377 1607 try: 1378 1608 f = open("%s/hosts" % configdir, "w") … … 1397 1627 self.auth.set_attribute(asignee, "%s/%s" % (configpath, f)) 1398 1628 1399 # Now, for each substrate in the main topology, find those that 1400 # have nodes on more than one testbed. Insert portal nodes 1401 # into the copies of those substrates on the sub topologies. 1402 for s in top.substrates: 1403 # tbs will contain an ip address on this subsrate that is in 1404 # each testbed. 1405 tbs = { } 1406 for i in s.interfaces: 1407 e = i.element 1408 tb = e.get_attribute('testbed') 1409 if tb and not tbs.has_key(tb): 1410 for i in e.interface: 1411 if s in i.subs: 1412 tbs[tb]= i.get_attribute('ip4_address') 1413 if len(tbs) < 2: 1414 continue 1415 1416 # More than one testbed is on this substrate. Insert 1417 # some portals into the subtopologies. st == source testbed, 1418 # dt == destination testbed. 1419 segment_substrate = { } 1420 for st in tbs.keys(): 1421 segment_substrate[st] = { } 1422 for dt in [ t for t in tbs.keys() if t != st]: 1423 myname = "%stunnel" % dt 1424 desthost = "%stunnel" % st 1425 sproject = tbparams[st].get('project', 'project') 1426 dproject = tbparams[dt].get('project', 'project') 1427 mproject = tbparams[master].get('project', 'project') 1428 sdomain = tbparams[st].get('domain', ".example.com") 1429 ddomain = tbparams[dt].get('domain', ".example.com") 1430 mdomain = tbparams[master].get('domain', '.example.com') 1431 muser = tbparams[master].get('user', 'root') 1432 smbshare = tbparams[master].get('smbshare', 'USERS') 1433 # XXX: active and type need to be unkludged 1434 active = ("%s" % (st == master)) 1435 if not segment_substrate[st].has_key(dt): 1436 # Put a substrate and a segment for the connected 1437 # testbed in there. 1438 tsubstrate = \ 1439 topdl.Substrate(name='%s-%s' % (st, dt), 1440 attribute= [ 1441 topdl.Attribute( 1442 attribute='portal', 1443 value='true') 1444 ] 1445 ) 1446 segment_element = topdl.Segment( 1447 id= tbparams[dt]['allocID'], 1448 type='emulab', 1449 uri = self.tbmap.get(dt, None), 1450 interface=[ 1451 topdl.Interface( 1452 substrate=tsubstrate.name), 1453 ], 1454 attribute = [ 1455 topdl.Attribute(attribute=n, value=v) 1456 for n, v in (\ 1457 ('domain', ddomain), 1458 ('experiment', "%s/%s" % \ 1459 (dproject, eid)),) 1460 ], 1461 ) 1462 segment_substrate[st][dt] = tsubstrate 1463 topo[st].substrates.append(tsubstrate) 1464 topo[st].elements.append(segment_element) 1465 portal = topdl.Computer( 1466 name="%stunnel" % dt, 1467 attribute=[ 1468 topdl.Attribute(attribute=n,value=v) 1469 for n, v in (\ 1470 ('portal', 'true'), 1471 ('domain', sdomain), 1472 ('masterdomain', mdomain), 1473 ('masterexperiment', "%s/%s" % \ 1474 (mproject, eid)), 1475 ('masteruser', muser), 1476 ('smbshare', smbshare), 1477 ('experiment', "%s/%s" % \ 1478 (sproject, eid)), 1479 ('peer', "%s" % desthost), 1480 ('peer_segment', "%s" % \ 1481 tbparams[dt]['allocID']['fedid']), 1482 ('scriptdir', 1483 "/usr/local/federation/bin"), 1484 ('active', "%s" % active), 1485 ('portal_type', 'both'), 1486 ('startup', 'sudo -H /usr/local/federation/bin/fed-tun.pl -f /proj/%s/exp/%s/tmp/%s.%s.%s%s.gw.conf >& /tmp/bridge.log' % (sproject, eid, myname.lower(), eid.lower(), sproject.lower(), sdomain.lower()))) 1487 ], 1488 interface=[ 1489 topdl.Interface( 1490 substrate=s.name, 1491 attribute=[ 1492 topdl.Attribute( 1493 attribute='ip4_address', 1494 value=tbs[dt] 1495 ) 1496 ]), 1497 topdl.Interface( 1498 substrate=\ 1499 segment_substrate[st][dt].name, 1500 attribute=[ 1501 topdl.Attribute(attribute='portal', 1502 value='true') 1503 ] 1504 ), 1505 ], 1506 ) 1507 if self.fedkit: add_kit(portal, self.fedkit) 1508 if self.gatewaykit: add_kit(portal, self.gatewaykit) 1509 1510 topo[st].elements.append(portal) 1511 1512 # Connect the gateway nodes into the topologies and clear out 1513 # substrates that are not in the topologies 1514 for tb in testbeds: 1515 topo[tb].incorporate_elements() 1516 topo[tb].substrates = \ 1517 [s for s in topo[tb].substrates \ 1518 if len(s.interfaces) >0] 1519 1520 # Copy the rpms and tarfiles to a distribution directory from 1521 # which the federants can retrieve them 1522 linkpath = "%s/software" % expid 1523 softdir ="%s/%s" % ( self.repodir, linkpath) 1524 softmap = { } 1525 pkgs = set([ t for l in [self.fedkit, self.gatewaykit] \ 1526 for p, t in l ]) 1527 pkgs.update([x.location for e in top.elements \ 1528 for x in e.software]) 1529 try: 1530 os.makedirs(softdir) 1531 except IOError, e: 1532 raise service_error( 1533 "Cannot create software directory: %s" % e) 1534 for pkg in pkgs: 1535 loc = pkg 1536 1537 scheme, host, path = urlparse(loc)[0:3] 1538 dest = os.path.basename(path) 1539 if not scheme: 1540 if not loc.startswith('/'): 1541 loc = "/%s" % loc 1542 loc = "file://%s" %loc 1543 try: 1544 u = urlopen(loc) 1545 except Exception, e: 1546 raise service_error(service_error.req, 1547 "Cannot open %s: %s" % (loc, e)) 1548 try: 1549 f = open("%s/%s" % (softdir, dest) , "w") 1550 self.log.debug("Writing %s/%s" % (softdir,dest) ) 1551 data = u.read(4096) 1552 while data: 1553 f.write(data) 1554 data = u.read(4096) 1555 f.close() 1556 u.close() 1557 except Exception, e: 1558 raise service_error(service_error.internal, 1559 "Could not copy %s: %s" % (loc, e)) 1560 path = re.sub("/tmp", "", linkpath) 1561 # XXX 1562 softmap[pkg] = \ 1563 "https://users.isi.deterlab.net:23232/%s/%s" %\ 1564 ( path, dest) 1565 1566 # Allow the individual testbeds to access the software. 1567 for tb in tbparams.keys(): 1568 self.auth.set_attribute(tbparams[tb]['allocID']['fedid'], 1569 "/%s/%s" % ( path, dest)) 1570 1571 # Convert the software locations in the segments into the local 1572 # copies on this host 1573 for soft in [ s for tb in topo.values() \ 1574 for e in tb.elements \ 1575 if getattr(e, 'software', False) \ 1576 for s in e.software ]: 1577 if softmap.has_key(soft.location): 1578 soft.location = softmap[soft.location] 1629 self.add_portals(top, topo, eid, master, tbparams) 1630 self.wrangle_software(expid, top, topo, tbparams) 1579 1631 1580 1632 vtopo = topdl.topology_to_vtopo(top)
Note: See TracChangeset
for help on using the changeset viewer.