- Timestamp:
- Apr 7, 2010 6:27:04 AM (15 years ago)
- Branches:
- axis_example, compt_changes, info-ops, master, version-3.01, version-3.02
- Children:
- 5f96438
- Parents:
- 7fe81be
- Location:
- fedd/federation
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
fedd/federation/experiment_control.py
r7fe81be r73e7f5c 29 29 from service_error import service_error 30 30 from synch_store import synch_store 31 from experiment_partition import experiment_partition 31 32 32 33 import topdl … … 1329 1330 topo[tb].make_indices() 1330 1331 1331 def new_portal_node(self, st, dt, tbparams, master, eid, myname, desthost,1332 portal_type, iface_desc=(), conn_type="ssh", conn_attrs=[],1333 expid=None):1334 """1335 Return a new internet portal node and a dict with the connectionInfo to1336 be attached.1337 """1338 dproject = tbparams[dt].get('project', 'project')1339 ddomain = tbparams[dt].get('domain', ".example.com")1340 mdomain = tbparams[master].get('domain', '.example.com')1341 mproject = tbparams[master].get('project', 'project')1342 muser = tbparams[master].get('user', 'root')1343 smbshare = tbparams[master].get('smbshare', 'USERS')1344 1345 if st == master or dt == master:1346 active = ("%s" % (st == master))1347 else:1348 active = ("%s" % (st > dt))1349 1350 ifaces = [ ]1351 for sub, attrs in iface_desc:1352 inf = topdl.Interface(1353 name="inf%03d" % len(ifaces),1354 substrate=sub,1355 attribute=[1356 topdl.Attribute(1357 attribute=n,1358 value = v)1359 for n, v in attrs1360 ]1361 )1362 ifaces.append(inf)1363 if conn_type == "ssh":1364 try:1365 aid = tbparams[st]['allocID']['fedid']1366 except:1367 self.log.debug("[new_portal_node] Can't get alloc id for %s?" \1368 % st)1369 aid = None1370 info = {1371 "type" : conn_type,1372 "portal": myname,1373 'fedAttr': [1374 { 'attribute': 'masterdomain', 'value': mdomain},1375 { 'attribute': 'masterexperiment', 'value':1376 "%s/%s" % (mproject, eid)},1377 { 'attribute': 'active', 'value': active},1378 # Move to SMB service description1379 { 'attribute': 'masteruser', 'value': muser},1380 { 'attribute': 'smbshare', 'value': smbshare},1381 ],1382 'parameter': [1383 {1384 'name': 'peer',1385 'key': 'fedid:%s/%s' % (expid, myname),1386 'store': self.store_url,1387 'type': 'output',1388 },1389 {1390 'name': 'ssh_port',1391 'key': 'fedid:%s/%s-port' % (expid, myname),1392 'store': self.store_url,1393 'type': 'output',1394 },1395 {1396 'name': 'peer',1397 'key': 'fedid:%s/%s' % (expid, desthost),1398 'store': self.store_url,1399 'type': 'input',1400 },1401 {1402 'name': 'ssh_port',1403 'key': 'fedid:%s/%s-port' % (expid, desthost),1404 'store': self.store_url,1405 'type': 'input',1406 },1407 ]1408 }1409 # Give this allocation the rights to access the key of the1410 # peers1411 if aid:1412 for h in (myname, desthost):1413 self.auth.set_attribute(aid, 'fedid:%s/%s' % (expid, h))1414 self.auth.set_attribute(aid, 'fedid:%s/%s-port' % \1415 (expid, h))1416 else:1417 self.log.error("No aid for %s in new_portal_node" % st)1418 else:1419 info = None1420 1421 return (topdl.Computer(1422 name=myname,1423 attribute=[1424 topdl.Attribute(attribute=n,value=v)1425 for n, v in (\1426 ('portal', 'true'),1427 ('portal_type', portal_type),1428 )1429 ],1430 interface=ifaces,1431 ), info)1432 1433 def new_portal_substrate(self, st, dt, eid, tbparams, expid):1434 ddomain = tbparams[dt].get('domain', ".example.com")1435 dproject = tbparams[dt].get('project', 'project')1436 tsubstrate = \1437 topdl.Substrate(name='%s-%s' % (st, dt),1438 attribute= [1439 topdl.Attribute(1440 attribute='portal',1441 value='true')1442 ]1443 )1444 segment_element = topdl.Segment(1445 id= tbparams[dt]['allocID'],1446 type='emulab',1447 uri = self.tbmap.get(dt, None),1448 interface=[1449 topdl.Interface(1450 substrate=tsubstrate.name),1451 ],1452 attribute = [1453 topdl.Attribute(attribute=n, value=v)1454 for n, v in (\1455 ('domain', ddomain),1456 ('experiment', "%s/%s" % \1457 (dproject, eid)),)1458 ],1459 )1460 1461 return (tsubstrate, segment_element)1462 1463 def new_dragon_topo(self, idx, sub, topo, tbs, tbparams, connInfo, expid):1464 if sub.capacity is None:1465 raise service_error(service_error.internal,1466 "Cannot DRAGON split substrate w/o capacity")1467 segs = [ ]1468 substr = topdl.Substrate(name="dragon%d" % idx,1469 capacity=sub.capacity.clone(),1470 attribute=[ topdl.Attribute(attribute=n, value=v)1471 for n, v, in (\1472 ('vlan', 'unassigned%d' % idx),)])1473 name = "dragon%d" % idx1474 store_key = 'fedid:%s/vlan%d' % (expid, idx)1475 for tb in tbs.keys():1476 seg = topdl.Segment(1477 id = tbparams[tb]['allocID'],1478 type='emulab',1479 uri = self.tbmap.get(tb, None),1480 interface=[1481 topdl.Interface(1482 substrate=substr.name),1483 ],1484 attribute=[ topdl.Attribute(1485 attribute='dragon_endpoint',1486 value=tbparams[tb]['dragon']),1487 ]1488 )1489 if tbparams[tb].has_key('vlans'):1490 seg.set_attribute('vlans', tbparams[tb]['vlans'])1491 segs.append(seg)1492 1493 # Give this allocation the rights to access the key of the1494 # vlan_id1495 try:1496 aid = tbparams[tb]['allocID']['fedid']1497 self.auth.set_attribute(aid, store_key)1498 except:1499 self.log.debug("[new_dragon_topo] Can't get alloc id for %s?"\1500 % tb)1501 1502 connInfo[name] = [ {1503 'type': 'transit',1504 'parameter': [ {1505 'name': 'vlan_id',1506 'key': store_key,1507 'store': self.store_url,1508 'type': 'output'1509 } ]1510 } ]1511 1512 topo[name] = \1513 topdl.Topology(substrates=[substr], elements=segs,1514 attribute=[1515 topdl.Attribute(attribute="transit", value='true'),1516 topdl.Attribute(attribute="dynamic", value='true'),1517 topdl.Attribute(attribute="testbed",1518 value='dragon'),1519 topdl.Attribute(attribute="store_keys",1520 value=store_key),1521 ]1522 )1523 1524 def create_dragon_substrate(self, sub, topo, tbs, tbparams, master, eid,1525 connInfo, expid=None):1526 """1527 Add attribiutes to the various elements indicating that they are to be1528 dragon connected and create a dragon segment in topo to be1529 instantiated.1530 """1531 1532 def get_substrate_from_topo(name, t):1533 for s in t.substrates:1534 if s.name == name: return s1535 else: return None1536 1537 1538 mdomain = tbparams[master].get('domain', '.example.com')1539 mproject = tbparams[master].get('project', 'project')1540 # dn is the number of previously created dragon nets. This routine1541 # creates a net numbered by dn1542 dn = len([x for x in topo.keys() if x.startswith('dragon')])1543 # Count the number of interfaces on this substrate in each testbed from1544 # the global topology1545 count = { }1546 node = { }1547 for e in [ i.element for i in sub.interfaces ]:1548 tb = e.get_attribute('testbed')1549 count[tb] = count.get(tb, 0) + 11550 node[tb] = i.get_attribute('ip4_address')1551 1552 1553 # Set the attributes in the copies that will allow setup of dragon1554 # connections.1555 for tb in tbs.keys():1556 s = get_substrate_from_topo(sub.name, topo[tb])1557 if s:1558 if not connInfo.has_key(tb):1559 connInfo[tb] = [ ]1560 1561 try:1562 aid = tbparams[tb]['allocID']['fedid']1563 except:1564 self.log.debug("[creat_dragon_substrate] " +1565 "Can't get alloc id for %s?" %tb)1566 aid = None1567 1568 # This may need another look, but only a service gateway will1569 # look at the active parameter, and these are only inserted to1570 # connect to the master.1571 active = "%s" % ( tb == master)1572 info = {1573 'type': 'transit',1574 'member': [ {1575 'element': i.element.name[0],1576 'interface': i.name1577 } for i in s.interfaces \1578 if isinstance(i.element, topdl.Computer) ],1579 'fedAttr': [1580 { 'attribute': 'masterdomain', 'value': mdomain},1581 { 'attribute': 'masterexperiment', 'value':1582 "%s/%s" % (mproject, eid)},1583 { 'attribute': 'active', 'value': active},1584 ],1585 'parameter': [ {1586 'name': 'vlan_id',1587 'key': 'fedid:%s/vlan%d' % (expid, dn),1588 'store': self.store_url,1589 'type': 'input',1590 } ]1591 }1592 if tbs.has_key(tb):1593 info['peer'] = tbs[tb]1594 connInfo[tb].append(info)1595 1596 # Give this allocation the rights to access the key of the1597 # vlan_id1598 if aid:1599 self.auth.set_attribute(aid,1600 'fedid:%s/vlan%d' % (expid, dn))1601 else:1602 raise service_error(service_error.internal,1603 "No substrate %s in testbed %s" % (sub.name, tb))1604 1605 self.new_dragon_topo(dn, sub, topo, tbs, tbparams, connInfo, expid)1606 1607 def insert_internet_portals(self, sub, topo, tbs, tbparams, master, eid,1608 segment_substrate, portals, connInfo, expid):1609 # More than one testbed is on this substrate. Insert1610 # some portals into the subtopologies. st == source testbed,1611 # dt == destination testbed.1612 for st in tbs.keys():1613 if not segment_substrate.has_key(st):1614 segment_substrate[st] = { }1615 if not portals.has_key(st):1616 portals[st] = { }1617 if not connInfo.has_key(st):1618 connInfo[st] = [ ]1619 for dt in [ t for t in tbs.keys() if t != st]:1620 sproject = tbparams[st].get('project', 'project')1621 dproject = tbparams[dt].get('project', 'project')1622 mproject = tbparams[master].get('project', 'project')1623 sdomain = tbparams[st].get('domain', ".example.com")1624 ddomain = tbparams[dt].get('domain', ".example.com")1625 mdomain = tbparams[master].get('domain', '.example.com')1626 muser = tbparams[master].get('user', 'root')1627 smbshare = tbparams[master].get('smbshare', 'USERS')1628 aid = tbparams[dt]['allocID']['fedid']1629 if st == master or dt == master:1630 active = ("%s" % (st == master))1631 else:1632 active = ("%s" %(st > dt))1633 if not segment_substrate[st].has_key(dt):1634 # Put a substrate and a segment for the connected1635 # testbed in there.1636 tsubstrate, segment_element = \1637 self.new_portal_substrate(st, dt, eid, tbparams,1638 expid)1639 segment_substrate[st][dt] = tsubstrate1640 topo[st].substrates.append(tsubstrate)1641 topo[st].elements.append(segment_element)1642 1643 new_portal = False1644 if portals[st].has_key(dt):1645 # There's a portal set up to go to this destination.1646 # See if there's room to multiplex this connection on1647 # it. If so, add an interface to the portal; if not,1648 # set up to add a portal below.1649 # [This little festival of braces is just a pop of the1650 # last element in the list of portals between st and1651 # dt.]1652 portal = portals[st][dt][-1]1653 mux = len([ i for i in portal.interface \1654 if not i.get_attribute('portal')])1655 if mux == self.muxmax:1656 new_portal = True1657 portal_type = "experiment"1658 myname = "%stunnel%d" % (dt, len(portals[st][dt]))1659 desthost = "%stunnel%d" % (st.lower(),1660 len(portals[st][dt]))1661 else:1662 new_i = topdl.Interface(1663 substrate=sub.name,1664 attribute=[1665 topdl.Attribute(1666 attribute='ip4_address',1667 value=tbs[dt]1668 )1669 ])1670 portal.interface.append(new_i)1671 else:1672 # First connection to this testbed, make an empty list1673 # and set up to add the new portal below1674 new_portal = True1675 portals[st][dt] = [ ]1676 myname = "%stunnel%d" % (dt, len(portals[st][dt]))1677 desthost = "%stunnel%d" % (st.lower(), len(portals[st][dt]))1678 1679 if dt == master or st == master: portal_type = "both"1680 else: portal_type = "experiment"1681 1682 if new_portal:1683 infs = (1684 (segment_substrate[st][dt].name,1685 (('portal', 'true'),)),1686 (sub.name,1687 (('ip4_address', tbs[dt]),))1688 )1689 portal, info = self.new_portal_node(st, dt, tbparams,1690 master, eid, myname, desthost, portal_type,1691 infs, conn_type="ssh", conn_attrs=[], expid=expid)1692 1693 topo[st].elements.append(portal)1694 portals[st][dt].append(portal)1695 connInfo[st].append(info)1696 1697 def add_control_portal(self, st, dt, master, eid, topo, tbparams, connInfo, expid):1698 # Add to the master testbed1699 tsubstrate, segment_element = \1700 self.new_portal_substrate(st, dt, eid, tbparams, expid)1701 myname = "%stunnel" % dt1702 desthost = "%stunnel" % st1703 1704 portal, info = self.new_portal_node(st, dt, tbparams, master,1705 eid, myname, desthost, "control",1706 ((tsubstrate.name,(('portal','true'),)),), conn_type="ssh",1707 conn_attrs=[], expid=expid)1708 1709 topo[st].substrates.append(tsubstrate)1710 topo[st].elements.append(segment_element)1711 topo[st].elements.append(portal)1712 if not connInfo.has_key(st):1713 connInfo[st] = [ ]1714 connInfo[st].append(info)1715 1716 def new_dragon_portal(self, st, dt, master, eid, myip, dip, idx,1717 substrate, tbparams, expid):1718 # Add to the master testbed1719 myname = "%stunnel" % dt1720 desthost = "%s" % ip_addr(dip)1721 1722 portal, info = self.new_portal_node(st, dt, tbparams, master,1723 eid, myname, desthost, "control",1724 ((substrate.name,(1725 ('portal','true'),1726 ('ip4_address', "%s" % ip_addr(myip)),)),),1727 conn_type="transit", conn_attrs=[], expid=expid)1728 1729 return portal1730 1731 def add_portals(self, top, topo, eid, master, tbparams, ip_allocator,1732 connInfo, expid):1733 """1734 For each substrate in the main topology, find those that1735 have nodes on more than one testbed. Insert portal nodes1736 into the copies of those substrates on the sub topologies.1737 """1738 segment_substrate = { }1739 portals = { }1740 for s in top.substrates:1741 # tbs will contain an ip address on this subsrate that is in1742 # each testbed.1743 tbs = { }1744 for i in s.interfaces:1745 e = i.element1746 tb = e.get_attribute('testbed')1747 if tb and not tbs.has_key(tb):1748 for i in e.interface:1749 if s in i.subs:1750 tbs[tb]= i.get_attribute('ip4_address')1751 if len(tbs) < 2:1752 continue1753 1754 # DRAGON will not create multi-site vlans yet1755 if len(tbs) == 2 and \1756 all([tbparams[x].has_key('dragon') for x in tbs]):1757 self.create_dragon_substrate(s, topo, tbs, tbparams,1758 master, eid, connInfo, expid)1759 else:1760 self.insert_internet_portals(s, topo, tbs, tbparams, master,1761 eid, segment_substrate, portals, connInfo, expid)1762 1763 # Make sure that all the slaves have a control portal back to the1764 # master.1765 for tb in [ t for t in tbparams.keys() if t != master ]:1766 if len([e for e in topo[tb].elements \1767 if isinstance(e, topdl.Computer) and \1768 e.get_attribute('portal') and \1769 e.get_attribute('portal_type') == 'both']) == 0:1770 1771 if tbparams[master].has_key('dragon') \1772 and tbparams[tb].has_key('dragon'):1773 1774 idx = len([x for x in topo.keys() \1775 if x.startswith('dragon')])1776 dip, leng = ip_allocator.allocate(4)1777 dip += 11778 mip = dip+11779 csub = topdl.Substrate(1780 name="dragon-control-%s" % tb,1781 capacity=topdl.Capacity(100000.0, 'max'),1782 attribute=[1783 topdl.Attribute(1784 attribute='portal',1785 value='true'1786 )1787 ]1788 )1789 seg = topdl.Segment(1790 id= tbparams[master]['allocID'],1791 type='emulab',1792 uri = self.tbmap.get(master, None),1793 interface=[1794 topdl.Interface(1795 substrate=csub.name),1796 ],1797 attribute = [1798 topdl.Attribute(attribute=n, value=v)1799 for n, v in (\1800 ('domain',1801 tbparams[master].get('domain',1802 ".example.com")),1803 ('experiment', "%s/%s" % \1804 (tbparams[master].get(1805 'project',1806 'project'),1807 eid)),)1808 ],1809 )1810 portal = self.new_dragon_portal(tb, master,1811 master, eid, dip, mip, idx, csub, tbparams, expid)1812 topo[tb].substrates.append(csub)1813 topo[tb].elements.append(portal)1814 topo[tb].elements.append(seg)1815 1816 mcsub = csub.clone()1817 seg = topdl.Segment(1818 id= tbparams[tb]['allocID'],1819 type='emulab',1820 uri = self.tbmap.get(tb, None),1821 interface=[1822 topdl.Interface(1823 substrate=csub.name),1824 ],1825 attribute = [1826 topdl.Attribute(attribute=n, value=v)1827 for n, v in (\1828 ('domain',1829 tbparams[tb].get('domain',1830 ".example.com")),1831 ('experiment', "%s/%s" % \1832 (tbparams[tb].get('project',1833 'project'),1834 eid)),)1835 ],1836 )1837 portal = self.new_dragon_portal(master, tb, master,1838 eid, mip, dip, idx, mcsub, tbparams, expid)1839 topo[master].substrates.append(mcsub)1840 topo[master].elements.append(portal)1841 topo[master].elements.append(seg)1842 for t in (master, tb):1843 topo[t].incorporate_elements()1844 1845 self.create_dragon_substrate(csub, topo,1846 {tb: ip_addr(mip), master: ip_addr(dip)},1847 tbparams, master, eid, connInfo,1848 expid)1849 else:1850 self.add_control_portal(master, tb, master, eid, topo,1851 tbparams, connInfo, expid)1852 self.add_control_portal(tb, master, master, eid, topo,1853 tbparams, connInfo, expid)1854 1855 # Connect the portal nodes into the topologies and clear out1856 # substrates that are not in the topologies1857 for tb in tbparams.keys():1858 topo[tb].incorporate_elements()1859 topo[tb].substrates = \1860 [s for s in topo[tb].substrates \1861 if len(s.interfaces) >0]1862 1863 1332 def wrangle_software(self, expid, top, topo, tbparams): 1864 1333 """ … … 2187 1656 self.auth.set_attribute(asignee, "%s/%s" % (configpath, f)) 2188 1657 2189 self.add_portals(top, topo, eid, master, tbparams, ip_allocator, 1658 part = experiment_partition(self.auth, self.store_url, self.tbmap, 1659 self.muxmax) 1660 part.add_portals(top, topo, eid, master, tbparams, ip_allocator, 2190 1661 connInfo, expid) 2191 1662 # Now get access to the dynamic testbeds
Note: See TracChangeset
for help on using the changeset viewer.