Changeset 69692a9


Ignore:
Timestamp:
Sep 21, 2009 6:48:12 PM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-2.00, version-3.01, version-3.02
Children:
ae0f69a
Parents:
adcbdaf
Message:

Looks like Dragon is being called correctly. Internals remain a bit messy.

Location:
fedd/federation
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • fedd/federation/dragon_access.py

    radcbdaf r69692a9  
    504504            if not ep:
    505505                raise service_error(service_error.req,
    506                         "Missing DRAGON endpoint foe %s" % s.name)
     506                        "Missing DRAGON endpoint for %s" % s.id)
    507507            v = s.get_attribute('vlans')
    508508            vlans = None
     
    669669            return gri, vlan_no
    670670        else:
    671             raise service_error(service_error.federant, "Cannot make reservation")
     671            raise service_error(service_error.federant,
     672                    "Cannot make reservation")
    672673
    673674    def stop_segment(self, repo, gri, log=None):
  • fedd/federation/emulab_access.py

    radcbdaf r69692a9  
    6969        self.ssh_privkey_file = config.get("access","ssh_privkey_file")
    7070        self.create_debug = config.getboolean("access", "create_debug")
     71        self.cleanup = not config.getboolean("access", "leave_tmpfiles")
    7172        self.access_type = config.get("access", "type")
    7273
     
    915916
    916917    def generate_ns2(self, topo, expfn, softdir, master):
     918        def dragon_commands(e):
     919            s = ""
     920            if isinstance(e, topdl.Computer):
     921                for i in e.interface:
     922                    vlan = i.get_attribute('dragon_vlan')
     923                    if vlan:
     924                        type = i.get_attribute('dragon_type')
     925                        ip = i.get_attribute('ip4_address')
     926                        if type == 'link':
     927                            s = ("tb-allow-external $%s dragonportal " + \
     928                                    "ip %s vlan %s\n") % \
     929                                    (topdl.to_tcl_name(e.name[0]), ip, vlan)
     930                        elif type == 'lan':
     931                            s = ("tb-allow-external $%s dragonportal " + \
     932                                    "ip %s vlan %s usurp %s\n") % \
     933                                    (topdl.to_tcl_name(e.name[0]), ip, vlan,
     934                                        i.substrate[0])
     935                        else:
     936                            raise service_error(service_error_internal,
     937                                    "Unknown DRAGON type %s" % type)
     938            return s
     939
     940        def not_dragon(e):
     941            return all([not i.get_attribute('dragon_vlan') \
     942                    for i in e.interface])
     943
    917944        t = topo.clone()
    918945
     
    925952            if isinstance(e, topdl.Computer):
    926953                e.interface = [i for i in e.interface \
    927                         if not i.get_attribute('portal')]
    928         t.substrates = [ s for s in t.substrates \
    929                 if not s.get_attribute('portal')]
     954                        if not i.get_attribute('portal') or \
     955                            i.get_attribute('dragon_vlan')]
     956        t.substrates = [ s.clone() for s in t.substrates ]
     957        #t.substrates = [ s for s in t.substrates \
     958        #       if not s.get_attribute('portal')]
    930959        t.incorporate_elements()
    931960
     
    941970        else:cmdname = 'SlaveConnectorCmd'
    942971
     972        if self.attrs.has_key('dragon'):
     973            add_filter = not_dragon
     974            filters.append(dragon_commands)
     975        else:
     976            add_filter = None
     977
    943978        if self.attrs.has_key(cmdname):
    944979            filters.append(topdl.generate_portal_command_filter(
    945                 self.attrs.get(cmdname)))
     980                self.attrs.get(cmdname), add_filter=add_filter))
    946981
    947982        if self.attrs.has_key('connectorImage'):
     
    10861121            err = e
    10871122
    1088         self.log.debug("[StartSegment]: removing %s" % tmpdir)
    10891123        # Walk up tmpdir, deleting as we go
    1090         for path, dirs, files in os.walk(tmpdir, topdown=False):
    1091             for f in files:
    1092                 os.remove(os.path.join(path, f))
    1093             for d in dirs:
    1094                 os.rmdir(os.path.join(path, d))
    1095         os.rmdir(tmpdir)
     1124        if self.cleanup:
     1125            self.log.debug("[StartSegment]: removing %s" % tmpdir)
     1126            for path, dirs, files in os.walk(tmpdir, topdown=False):
     1127                for f in files:
     1128                    os.remove(os.path.join(path, f))
     1129                for d in dirs:
     1130                    os.rmdir(os.path.join(path, d))
     1131            os.rmdir(tmpdir)
     1132        else:
     1133            self.log.debug("[StartSegment]: not removing %s" % tmpdir)
    10961134
    10971135        if rv:
  • fedd/federation/experiment_control.py

    radcbdaf r69692a9  
    233233
    234234        self.debug = config.getboolean("experiment_control", "create_debug")
     235        self.cleanup = not config.getboolean("experiment_control",
     236                "leave_tmpfiles")
    235237        self.state_filename = config.get("experiment_control",
    236238                "experiment_state")
     
    816818                    "Access denied by %s (%s)" % (tb, uri))
    817819
    818         e = r['emulab']
    819         p = e['project']
    820         tbparam[tb] = {
    821                 "boss": e['boss'],
    822                 "host": e['ops'],
    823                 "domain": e['domain'],
    824                 "fs": e['fileServer'],
    825                 "eventserver": e['eventServer'],
    826                 "project": unpack_id(p['name']),
    827                 "emulab" : e,
    828                 "allocID" : r['allocID'],
    829                 }
    830         # Make the testbed name be the label the user applied
    831         p['testbed'] = {'localname': tb }
    832 
    833         for u in p['user']:
    834             role = u.get('role', None)
    835             if role == 'experimentCreation':
    836                 tbparam[tb]['user'] = unpack_id(u['userID'])
    837                 break
    838         else:
    839             raise service_error(service_error.internal,
    840                     "No createExperimentUser from %s" %tb)
    841 
    842         # Add attributes to barameter space.  We don't allow attributes to
    843         # overlay any parameters already installed.
    844         for a in e['fedAttr']:
    845             try:
    846                 if a['attribute'] and isinstance(a['attribute'], basestring)\
    847                         and not tbparam[tb].has_key(a['attribute'].lower()):
    848                     tbparam[tb][a['attribute'].lower()] = a['value']
    849             except KeyError:
    850                 self.log.error("Bad attribute in response: %s" % a)
     820        if r.has_key('emulab'):
     821            e = r['emulab']
     822            p = e['project']
     823            tbparam[tb] = {
     824                    "boss": e['boss'],
     825                    "host": e['ops'],
     826                    "domain": e['domain'],
     827                    "fs": e['fileServer'],
     828                    "eventserver": e['eventServer'],
     829                    "project": unpack_id(p['name']),
     830                    "emulab" : e,
     831                    "allocID" : r['allocID'],
     832                    "uri": uri,
     833                    }
     834            # Make the testbed name be the label the user applied
     835            p['testbed'] = {'localname': tb }
     836
     837            for u in p['user']:
     838                role = u.get('role', None)
     839                if role == 'experimentCreation':
     840                    tbparam[tb]['user'] = unpack_id(u['userID'])
     841                    break
     842            else:
     843                raise service_error(service_error.internal,
     844                        "No createExperimentUser from %s" %tb)
     845            # Add attributes to parameter space.  We don't allow attributes to
     846            # overlay any parameters already installed.
     847            for a in e['fedAttr']:
     848                try:
     849                    if a['attribute'] and \
     850                            isinstance(a['attribute'], basestring)\
     851                            and not tbparam[tb].has_key(a['attribute'].lower()):
     852                        tbparam[tb][a['attribute'].lower()] = a['value']
     853                except KeyError:
     854                    self.log.error("Bad attribute in response: %s" % a)
     855        else:
     856            tbparam[tb] = {
     857                "allocID" : r['allocID'],
     858                "uri": uri,
     859            }
     860
    851861       
    852     def release_access(self, tb, aid):
     862    def release_access(self, tb, aid, uri=None):
    853863        """
    854864        Release access to testbed through fedd
    855865        """
    856866
    857         uri = self.tbmap.get(tb, None)
     867        if not uri:
     868            uri = self.tbmap.get(tb, None)
    858869        if not uri:
    859             raise service_error(serice_error.server_config,
     870            raise service_error(service_error.server_config,
    860871                    "Unknown testbed: %s" % tb)
    861872
     
    905916            self.testbed = testbed
    906917            self.log_collector = log_collector
     918            self.response = None
    907919
    908920        def __call__(self, uri, aid, topo, master, attrs=None):
     
    927939                        for line in  lval.splitlines(True):
    928940                            self.log_collector.write(line)
     941                    self.response = r
    929942                else:
    930943                    raise service_error(service_error.internal,
     
    966979            tbparams, topo, tmpdir, alloc_log=None, log_collector=None,
    967980            attrs=None):
     981        def get_vlan(r):
     982            if r.has_key('StartSegmentResponseBody'):
     983                srb = r['StartSegmentResponseBody']
     984                if srb.has_key('fedAttr'):
     985                    for k, v in [ (a['attribute'], a['value']) \
     986                            for a in srb['fedAttr']]:
     987                        if k == 'vlan': return v
     988            return None
     989
    968990        started = { }           # Testbeds where a sub-experiment started
    969991                                # successfully
     
    972994        fail_soft = False
    973995
     996        slaves = [ k for k in allocated.keys() \
     997                if k != master and not topo[k].get_attribute('transit')]
     998        transit = [ k for k in allocated.keys() \
     999                if topo[k].get_attribute('transit')]
     1000
    9741001        log = alloc_log or self.log
    9751002
     
    9771004        threads = [ ]
    9781005
    979         for tb in [ k for k in allocated.keys() if k != master]:
    980             # Create and start a thread to start the segment, and save it to
    981             # get the return value later
    982             thread_pool.wait_for_slot()
    983             uri = self.tbmap.get(tb, None)
    984             if not uri:
    985                 raise service_error(service_error.internal,
    986                         "Unknown testbed %s !?" % tb)
    987 
     1006        for tb in transit:
     1007            uri = tbparams[tb]['uri']
    9881008            if tbparams[tb].has_key('allocID') and \
    9891009                    tbparams[tb]['allocID'].has_key('fedid'):
     
    9931013                        "No alloc id for testbed %s !?" % tb)
    9941014
    995             t  = self.pooled_thread(\
    996                     target=self.start_segment(log=log, debug=self.debug,
    997                         testbed=tb, cert_file=self.cert_file,
    998                         cert_pwd=self.cert_pwd,
    999                         trusted_certs=self.trusted_certs,
    1000                         caller=self.call_StartSegment,
    1001                         log_collector=log_collector),
    1002                     args=(uri, aid, topo[tb], False, attrs), name=tb,
    1003                     pdata=thread_pool, trace_file=self.trace_file)
    1004             threads.append(t)
    1005             t.start()
    1006 
    1007         # Wait until all finish (keep pinging the log, though)
    1008         mins = 0
    1009         while not thread_pool.wait_for_all_done(60.0):
    1010             mins += 1
    1011             alloc_log.info("Waiting for sub threads (it has been %d mins)" \
    1012                     % mins)
    1013 
    1014         thread_pool.clear()
     1015            m = re.search('(\d+)', tb)
     1016            if m:
     1017                to_repl = "unassigned%s" % m.group(1)
     1018            else:
     1019                raise service_error(service_error.internal,
     1020                        "Bad dynamic allocation name")
     1021                break
     1022
     1023            ss = self.start_segment(log=log, debug=self.debug,
     1024                testbed=master, cert_file=self.cert_file,
     1025                cert_pwd=self.cert_pwd,
     1026                trusted_certs=self.trusted_certs,
     1027                caller=self.call_StartSegment,
     1028                log_collector=log_collector)
     1029            t = self.pooled_thread(
     1030                    target=ss,
     1031                    args =(uri, aid, topo[tb], False, attrs),
     1032                    name=tb, pdata=thread_pool, trace_file=self.trace_file)
     1033            threads.append(t)
     1034            t.start()
     1035            # Wait until the this transit node finishes (keep pinging the log,
     1036            # though)
     1037
     1038            mins = 0
     1039            while not thread_pool.wait_for_all_done(60.0):
     1040                mins += 1
     1041                alloc_log.info("Waiting for master (it has been %d mins)" \
     1042                        % mins)
     1043
     1044            if t.rv:
     1045                vlan = get_vlan(ss.response)
     1046                if vlan is not None:
     1047                    for k, t in topo.items():
     1048                        for e in t.elements:
     1049                            for i in e.interface:
     1050                                vl = i.get_attribute('dragon_vlan')
     1051                                if vl is not None and vl == to_repl:
     1052                                    i.set_attribute('dragon_vlan', vlan)
     1053            else:
     1054                break
     1055            thread_pool.clear()
     1056
     1057
     1058        failed = [ t.getName() for t in threads if not t.rv ]
     1059
     1060        if len(failed) == 0:
     1061            for tb in slaves:
     1062                # Create and start a thread to start the segment, and save it
     1063                # to get the return value later
     1064                thread_pool.wait_for_slot()
     1065                uri = self.tbmap.get(tb, None)
     1066                if not uri:
     1067                    raise service_error(service_error.internal,
     1068                            "Unknown testbed %s !?" % tb)
     1069
     1070                if tbparams[tb].has_key('allocID') and \
     1071                        tbparams[tb]['allocID'].has_key('fedid'):
     1072                    aid = tbparams[tb]['allocID']['fedid']
     1073                else:
     1074                    raise service_error(service_error.internal,
     1075                            "No alloc id for testbed %s !?" % tb)
     1076
     1077                t  = self.pooled_thread(\
     1078                        target=self.start_segment(log=log, debug=self.debug,
     1079                            testbed=tb, cert_file=self.cert_file,
     1080                            cert_pwd=self.cert_pwd,
     1081                            trusted_certs=self.trusted_certs,
     1082                            caller=self.call_StartSegment,
     1083                            log_collector=log_collector),
     1084                        args=(uri, aid, topo[tb], False, attrs), name=tb,
     1085                        pdata=thread_pool, trace_file=self.trace_file)
     1086                threads.append(t)
     1087                t.start()
     1088
     1089            # Wait until all finish (keep pinging the log, though)
     1090            mins = 0
     1091            while not thread_pool.wait_for_all_done(60.0):
     1092                mins += 1
     1093                alloc_log.info("Waiting for sub threads (it has been %d mins)" \
     1094                        % mins)
     1095
     1096            thread_pool.clear()
    10151097
    10161098        # If none failed, start the master
     
    10741156                # release the allocations
    10751157                for tb in tbparams.keys():
    1076                     self.release_access(tb, tbparams[tb]['allocID'])
     1158                    self.release_access(tb, tbparams[tb]['allocID'],
     1159                            tbparams[tb].get('uri', None))
    10771160                # Remove the placeholder
    10781161                self.state_lock.acquire()
     
    10861169            log.info("[start_segment]: Experiment %s active" % eid)
    10871170
    1088         log.debug("[start_experiment]: removing %s" % tmpdir)
    10891171
    10901172        # Walk up tmpdir, deleting as we go
    1091         for path, dirs, files in os.walk(tmpdir, topdown=False):
    1092             for f in files:
    1093                 os.remove(os.path.join(path, f))
    1094             for d in dirs:
    1095                 os.rmdir(os.path.join(path, d))
    1096         os.rmdir(tmpdir)
     1173        if self.cleanup:
     1174            log.debug("[start_experiment]: removing %s" % tmpdir)
     1175            for path, dirs, files in os.walk(tmpdir, topdown=False):
     1176                for f in files:
     1177                    os.remove(os.path.join(path, f))
     1178                for d in dirs:
     1179                    os.rmdir(os.path.join(path, d))
     1180            os.rmdir(tmpdir)
     1181        else:
     1182            log.debug("[start_experiment]: not removing %s" % tmpdir)
    10971183
    10981184        # Insert the experiment into our state and update the disk copy
     
    11901276    def allocate_ips_to_topo(self, top):
    11911277        """
    1192         Add an ip4_address attribute to all the hosts in teh topology, based on
     1278        Add an ip4_address attribute to all the hosts in the topology, based on
    11931279        the shared substrates on which they sit.  An /etc/hosts file is also
    1194         created and returned as a list of hostfiles entries.
     1280        created and returned as a list of hostfiles entries.  We also return
     1281        the allocator, because we may need to allocate IPs to portals
     1282        (specifically DRAGON portals).
    11951283        """
    11961284        subs = sorted(top.substrates,
     
    12301318                ifs[hname] += 1
    12311319                base += 1
    1232         return hosts
     1320        return hosts, ips
    12331321
    12341322    def get_access_to_testbeds(self, testbeds, user, access_user,
     
    12831371
    12841372    def new_portal_node(self, st, dt, tbparams, master, eid, myname, desthost,
    1285             portal_type, portal_subst, subst=None, addr=None):
     1373            portal_type, iface_desc=()):
    12861374        sproject = tbparams[st].get('project', 'project')
    12871375        dproject = tbparams[dt].get('project', 'project')
     
    12981386            active = ("%s" %(st > dt))
    12991387
    1300         ifaces = [
    1301             topdl.Interface(
    1302                 substrate=portal_subst,
    1303                 attribute=[
    1304                     topdl.Attribute(attribute='portal',
    1305                         value='true')
    1306                     ]
    1307                 ),
    1308             ]
    1309         if subst and addr:
    1310             ifaces.append(
    1311                     topdl.Interface(
    1312                         substrate=subst,
    1313                         attribute=[
    1314                             topdl.Attribute(
    1315                                 attribute='ip4_address',
    1316                                 value=addr,
    1317                             )
     1388        ifaces = [ ]
     1389        for sub, attrs in iface_desc:
     1390            inf = topdl.Interface(
     1391                    substrate=sub,
     1392                    attribute=[
     1393                        topdl.Attribute(
     1394                            attribute=n,
     1395                            value = v)
     1396                        for n, v in attrs
    13181397                        ]
    1319                         ))
    1320 
    1321 
     1398                    )
     1399            ifaces.append(inf)
    13221400        return topdl.Computer(
    13231401                name=myname,
     
    13401418                            ('active', "%s" % active),
    13411419                            ('portal_type', portal_type),
    1342                             ('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())))
     1420                            ('startup', 'sudo -H /usr/local/federation/bin/fed-tun.pl >& /tmp/bridge.log'))
    13431421                    ],
    13441422                interface=ifaces,
     
    13751453        return (tsubstrate, segment_element)
    13761454
    1377     def add_portals(self, top, topo, eid, master, tbparams):
     1455    def new_dragon_topo(self, idx, sub, topo, tbs, tbparams):
     1456        if sub.capacity is None:
     1457            raise service_error(service_error.internal,
     1458                    "Cannot DRAGON split substrate w/o capacity")
     1459        segs = [ ]
     1460        substr = topdl.Substrate(name="dragon%d" % idx,
     1461                capacity=sub.capacity.clone(),
     1462                attribute=[ topdl.Attribute(attribute=n, value=v)
     1463                    for n, v, in (\
     1464                            ('vlan', 'unassigned%d' % idx),)])
     1465        for tb in tbs.keys():
     1466            seg = topdl.Segment(
     1467                    id = tbparams[tb]['allocID'],
     1468                    type='emulab',
     1469                    uri = self.tbmap.get(tb, None),
     1470                    interface=[
     1471                        topdl.Interface(
     1472                            substrate=substr.name),
     1473                        ],
     1474                    attribute=[ topdl.Attribute(
     1475                        attribute='dragon_endpoint', value='true'),
     1476                        ]
     1477                    )
     1478            if tbparams[tb].has_key('vlans'):
     1479                seg.set_attribute('vlans', tbparams[tb]['vlans'])
     1480            segs.append(seg)
     1481
     1482        topo["dragon%d" %idx] = \
     1483                topdl.Topology(substrates=[substr], elements=segs,
     1484                        attribute=[
     1485                            topdl.Attribute(attribute="transit", value='true'),
     1486                            topdl.Attribute(attribute="dynamic", value='true'),
     1487                            topdl.Attribute(attribute="testbed", value='dragon'),
     1488                            ]
     1489                        )
     1490
     1491    def create_dragon_substrate(self, sub, topo, tbs, tbparams, master, eid):
     1492        """
     1493        Add attribiutes to the various elements indicating that they are to be
     1494        dragon connected and create a dragon segment in tops to be
     1495        instantiated.
     1496        """
     1497
     1498        def get_substrate_from_topo(name, t):
     1499            for s in t.substrates:
     1500                if s.name == name: return s
     1501            else: return None
     1502
     1503        dn = len([x for x in topo.keys() if x.startswith('dragon')])
     1504        elements = [ i.element for i in sub.interfaces ]
     1505        count = { }
     1506        for e in elements:
     1507            tb = e.get_attribute('testbed')
     1508            count[tb] = count.get(tb, 0) + 1
     1509
     1510        for tb in tbs.keys():
     1511            s = get_substrate_from_topo(sub.name, topo[tb])
     1512            if s:
     1513                for i in s.interfaces:
     1514                    i.set_attribute('dragon_vlan', 'unassigned%d' % dn)
     1515                    if count[tb] > 1: i.set_attribute('dragon_type', 'lan')
     1516                    else: i.set_attribute('dragon_type', 'link')
     1517            else:
     1518                raise service_error(service_error.internal,
     1519                        "No substrate %s in testbed %s" % (sub.name, tb))
     1520
     1521        self.new_dragon_topo(dn, sub, topo, tbs, tbparams)
     1522
     1523    def insert_internet_portals(self, sub, topo, tbs, tbparams, master, eid,
     1524            segment_substrate, portals):
     1525        # More than one testbed is on this substrate.  Insert
     1526        # some portals into the subtopologies.  st == source testbed,
     1527        # dt == destination testbed.
     1528        for st in tbs.keys():
     1529            if not segment_substrate.has_key(st):
     1530                segment_substrate[st] = { }
     1531            if not portals.has_key(st):
     1532                portals[st] = { }
     1533            for dt in [ t for t in tbs.keys() if t != st]:
     1534                sproject = tbparams[st].get('project', 'project')
     1535                dproject = tbparams[dt].get('project', 'project')
     1536                mproject = tbparams[master].get('project', 'project')
     1537                sdomain = tbparams[st].get('domain', ".example.com")
     1538                ddomain = tbparams[dt].get('domain', ".example.com")
     1539                mdomain = tbparams[master].get('domain', '.example.com')
     1540                muser = tbparams[master].get('user', 'root')
     1541                smbshare = tbparams[master].get('smbshare', 'USERS')
     1542                aid = tbparams[dt]['allocID']['fedid']
     1543                if st == master or dt == master:
     1544                    active = ("%s" % (st == master))
     1545                else:
     1546                    active = ("%s" %(st > dt))
     1547                if not segment_substrate[st].has_key(dt):
     1548                    # Put a substrate and a segment for the connected
     1549                    # testbed in there.
     1550                    tsubstrate, segment_element = \
     1551                            self.new_portal_substrate(st, dt, eid, tbparams)
     1552                    segment_substrate[st][dt] = tsubstrate
     1553                    topo[st].substrates.append(tsubstrate)
     1554                    topo[st].elements.append(segment_element)
     1555
     1556                new_portal = False
     1557                if portals[st].has_key(dt):
     1558                    # There's a portal set up to go to this destination.
     1559                    # See if there's room to multiples this connection on
     1560                    # it.  If so, add an interface to the portal; if not,
     1561                    # set up to add a portal below.
     1562                    # [This little festival of braces is just a pop of the
     1563                    # last element in the list of portals between st and
     1564                    # dt.]
     1565                    portal = portals[st][dt][-1]
     1566                    mux = len([ i for i in portal.interface \
     1567                            if not i.get_attribute('portal')])
     1568                    if mux == self.muxmax:
     1569                        new_portal = True
     1570                        portal_type = "experiment"
     1571                        myname = "%stunnel%d" % (dt, len(portals[st][dt]))
     1572                        desthost = "%stunnel%d" % (st, len(portals[st][dt]))
     1573                    else:
     1574                        new_i = topdl.Interface(
     1575                                substrate=s.name,
     1576                                attribute=[
     1577                                    topdl.Attribute(
     1578                                        attribute='ip4_address',
     1579                                        value=tbs[dt]
     1580                                    )
     1581                                ])
     1582                        portal.interface.append(new_i)
     1583                else:
     1584                    # First connection to this testbed, make an empty list
     1585                    # and set up to add the new portal below
     1586                    new_portal = True
     1587                    portals[st][dt] = [ ]
     1588                    myname = "%stunnel%d" % (dt, len(portals[st][dt]))
     1589                    desthost = "%stunnel%d" % (st, len(portals[st][dt]))
     1590
     1591                    if dt == master or st == master: portal_type = "both"
     1592                    else: portal_type = "experiment"
     1593
     1594                if new_portal:
     1595                    infs = (
     1596                            (segment_substrate[st][dt].name,
     1597                                (('portal', 'true'),)),
     1598                            (sub.name,
     1599                                (('ip4_address', tbs[dt]),))
     1600                        )
     1601                    portal =  self.new_portal_node(st, dt, tbparams,
     1602                            master, eid, myname, desthost, portal_type,
     1603                            infs)
     1604                    if self.fedkit:
     1605                        self.add_kit(portal, self.fedkit)
     1606                    if self.gatewaykit:
     1607                        self.add_kit(portal, self.gatewaykit)
     1608
     1609                    topo[st].elements.append(portal)
     1610                    portals[st][dt].append(portal)
     1611
     1612    def add_control_portal(self, st, dt, master, eid, topo, tbparams):
     1613        # Add to the master testbed
     1614        tsubstrate, segment_element = \
     1615                self.new_portal_substrate(st, dt, eid, tbparams)
     1616        myname = "%stunnel" % dt
     1617        desthost = "%stunnel" % st
     1618
     1619        portal = self.new_portal_node(st, dt, tbparams, master,
     1620                eid, myname, desthost, "control",
     1621                ((tsubstrate.name,(('portal','true'),)),))
     1622        if self.fedkit:
     1623            self.add_kit(portal, self.fedkit)
     1624        if self.gatewaykit:
     1625            self.add_kit(portal, self.gatewaykit)
     1626
     1627        topo[st].substrates.append(tsubstrate)
     1628        topo[st].elements.append(segment_element)
     1629        topo[st].elements.append(portal)
     1630
     1631    def new_dragon_portal(self, st, dt, master, eid, dip, idx,
     1632            substrate, tbparams):
     1633        # Add to the master testbed
     1634        myname = "%stunnel" % dt
     1635        desthost = "%s" % ip_addr(dip)
     1636
     1637        portal = self.new_portal_node(st, dt, tbparams, master,
     1638                eid, myname, desthost, "control",
     1639                ((substrate.name,(
     1640                    ('portal','true'),
     1641                    ('ip4_address', "%s" % ip_addr(dip)),
     1642                    ('dragon_vlan', 'unassigned%d' % idx),
     1643                    ('dragon_type', 'link'),)),))
     1644        if self.fedkit:
     1645            self.add_kit(portal, self.fedkit)
     1646        if self.gatewaykit:
     1647            self.add_kit(portal, self.gatewaykit)
     1648
     1649        return portal
     1650
     1651    def add_portals(self, top, topo, eid, master, tbparams, ip_allocator):
    13781652        """
    13791653        For each substrate in the main topology, find those that
     
    13971671                continue
    13981672
    1399             # More than one testbed is on this substrate.  Insert
    1400             # some portals into the subtopologies.  st == source testbed,
    1401             # dt == destination testbed.
    1402             for st in tbs.keys():
    1403                 if not segment_substrate.has_key(st):
    1404                     segment_substrate[st] = { }
    1405                 if not portals.has_key(st):
    1406                     portals[st] = { }
    1407                 for dt in [ t for t in tbs.keys() if t != st]:
    1408                     sproject = tbparams[st].get('project', 'project')
    1409                     dproject = tbparams[dt].get('project', 'project')
    1410                     mproject = tbparams[master].get('project', 'project')
    1411                     sdomain = tbparams[st].get('domain', ".example.com")
    1412                     ddomain = tbparams[dt].get('domain', ".example.com")
    1413                     mdomain = tbparams[master].get('domain', '.example.com')
    1414                     muser = tbparams[master].get('user', 'root')
    1415                     smbshare = tbparams[master].get('smbshare', 'USERS')
    1416                     aid = tbparams[dt]['allocID']['fedid']
    1417                     if st == master or dt == master:
    1418                         active = ("%s" % (st == master))
    1419                     else:
    1420                         active = ("%s" %(st > dt))
    1421                     if not segment_substrate[st].has_key(dt):
    1422                         # Put a substrate and a segment for the connected
    1423                         # testbed in there.
    1424                         tsubstrate, segment_element = \
    1425                                 self.new_portal_substrate(st, dt, eid, tbparams)
    1426                         segment_substrate[st][dt] = tsubstrate
    1427                         topo[st].substrates.append(tsubstrate)
    1428                         topo[st].elements.append(segment_element)
    1429 
    1430                     new_portal = False
    1431                     if portals[st].has_key(dt):
    1432                         # There's a portal set up to go to this destination.
    1433                         # See if there's room to multiples this connection on
    1434                         # it.  If so, add an interface to the portal; if not,
    1435                         # set up to add a portal below.
    1436                         # [This little festival of braces is just a pop of the
    1437                         # last element in the list of portals between st and
    1438                         # dt.]
    1439                         portal = portals[st][dt][-1]
    1440                         mux = len([ i for i in portal.interface \
    1441                                 if not i.get_attribute('portal')])
    1442                         if mux == self.muxmax:
    1443                             new_portal = True
    1444                             portal_type = "experiment"
    1445                             myname = "%stunnel%d" % (dt, len(portals[st][dt]))
    1446                             desthost = "%stunnel%d" % (st, len(portals[st][dt]))
    1447                         else:
    1448                             new_i = topdl.Interface(
    1449                                     substrate=s.name,
    1450                                     attribute=[
    1451                                         topdl.Attribute(
    1452                                             attribute='ip4_address',
    1453                                             value=tbs[dt]
    1454                                         )
    1455                                     ])
    1456                             portal.interface.append(new_i)
    1457                     else:
    1458                         # First connection to this testbed, make an empty list
    1459                         # and set up to add the new portal below
    1460                         new_portal = True
    1461                         portals[st][dt] = [ ]
    1462                         myname = "%stunnel%d" % (dt, len(portals[st][dt]))
    1463                         desthost = "%stunnel%d" % (st, len(portals[st][dt]))
    1464 
    1465                         if dt == master or st == master: portal_type = "both"
    1466                         else: portal_type = "experiment"
    1467 
    1468                     if new_portal:
    1469                         portal =  self.new_portal_node(st, dt, tbparams,
    1470                                 master, eid, myname, desthost, portal_type,
    1471                                 segment_substrate[st][dt].name, s.name, tbs[dt])
    1472                         if self.fedkit:
    1473                             self.add_kit(portal, self.fedkit)
    1474                         if self.gatewaykit:
    1475                             self.add_kit(portal, self.gatewaykit)
    1476 
    1477                         topo[st].elements.append(portal)
    1478                         portals[st][dt].append(portal)
     1673            # DRAGON will not create multi-site vlans yet
     1674            if len(tbs) == 2 and \
     1675                    all([tbparams[x].has_key('dragon') for x in tbs]):
     1676                self.create_dragon_substrate(s, topo, tbs, tbparams,
     1677                        master, eid)
     1678            else:
     1679                self.insert_internet_portals(s, topo, tbs, tbparams, master,
     1680                        eid, segment_substrate, portals)
    14791681
    14801682        # Make sure that all the slaves have a control portal back to the
     
    14861688                    e.get_attribute('portal_type') == 'both']) == 0:
    14871689
    1488                 # Add to the master testbed
    1489                 tsubstrate, segment_element = \
    1490                         self.new_portal_substrate(master, tb, eid, tbparams)
    1491                 myname = "%stunnel" % tb
    1492                 desthost = "%stunnel" % master
    1493 
    1494                 portal = self.new_portal_node(master, tb, tbparams, master,
    1495                         eid, myname, desthost, "control", tsubstrate.name)
    1496                 if self.fedkit:
    1497                     self.add_kit(portal, self.fedkit)
    1498                 if self.gatewaykit:
    1499                     self.add_kit(portal, self.gatewaykit)
    1500 
    1501                 topo[master].substrates.append(tsubstrate)
    1502                 topo[master].elements.append(segment_element)
    1503                 topo[master].elements.append(portal)
    1504 
    1505                 # And to the other testbed
    1506 
    1507                 tsubstrate, segment_element = \
    1508                         self.new_portal_substrate(tb, master, eid, tbparams)
    1509                 myname = "%stunnel" % master
    1510                 desthost = "%stunnel" % tb
    1511 
    1512                 portal = self.new_portal_node(tb, master, tbparams, master,
    1513                         eid, myname, desthost, "control", tsubstrate.name)
    1514                 if self.fedkit:
    1515                     self.add_kit(portal, self.fedkit)
    1516                 if self.gatewaykit:
    1517                     self.add_kit(portal, self.gatewaykit)
    1518 
    1519                 topo[tb].substrates.append(tsubstrate)
    1520                 topo[tb].elements.append(segment_element)
    1521                 topo[tb].elements.append(portal)
    1522 
     1690                if tbparams[master].has_key('dragon') \
     1691                        and tbparams[tb].has_key('dragon'):
     1692
     1693                    idx = len([x for x in topo.keys() \
     1694                            if x.startswith('dragon')])
     1695                    dip, leng = ip_allocator.allocate(4)
     1696                    dip += 1
     1697                    csub = topdl.Substrate(
     1698                            name="dragon-control-%s" % tb,
     1699                            capacity=topdl.Capacity(100000.0, 'max'),
     1700                            attribute=[
     1701                                topdl.Attribute(
     1702                                    attribute='portal',
     1703                                    value='true'
     1704                                    )
     1705                                ]
     1706                            )
     1707                    seg = topdl.Segment(
     1708                            id= tbparams[master]['allocID'],
     1709                            type='emulab',
     1710                            uri = self.tbmap.get(master, None),
     1711                            interface=[
     1712                                topdl.Interface(
     1713                                    substrate=csub.name),
     1714                                ],
     1715                            attribute = [
     1716                                topdl.Attribute(attribute=n, value=v)
     1717                                    for n, v in (\
     1718                                        ('domain',
     1719                                            tbparams[master].get('domain',
     1720                                                ".example.com")),
     1721                                        ('experiment', "%s/%s" % \
     1722                                                (tbparams[master].get(
     1723                                                    'project',
     1724                                                    'project'),
     1725                                                    eid)),)
     1726                                ],
     1727                            )
     1728                    topo[tb].substrates.append(csub)
     1729                    topo[tb].elements.append(
     1730                            self.new_dragon_portal(tb, master, master, eid,
     1731                                dip, idx, csub, tbparams))
     1732                    topo[tb].elements.append(seg)
     1733
     1734                    dip+=1
     1735                    mcsub = csub.clone()
     1736                    seg = topdl.Segment(
     1737                            id= tbparams[tb]['allocID'],
     1738                            type='emulab',
     1739                            uri = self.tbmap.get(tb, None),
     1740                            interface=[
     1741                                topdl.Interface(
     1742                                    substrate=csub.name),
     1743                                ],
     1744                            attribute = [
     1745                                topdl.Attribute(attribute=n, value=v)
     1746                                    for n, v in (\
     1747                                        ('domain',
     1748                                            tbparams[tb].get('domain',
     1749                                                ".example.com")),
     1750                                        ('experiment', "%s/%s" % \
     1751                                                (tbparams[tb].get('project',
     1752                                                    'project'),
     1753                                                    eid)),)
     1754                                ],
     1755                            )
     1756                    topo[master].substrates.append(mcsub)
     1757                    topo[master].elements.append(
     1758                            self.new_dragon_portal(master, tb, master, eid,
     1759                                dip, idx, mcsub, tbparams))
     1760                    topo[master].elements.append(seg)
     1761
     1762                    self.create_dragon_substrate(csub, topo,
     1763                            {tb: 1, master:1}, tbparams, master, eid)
     1764                else:
     1765                    self.add_control_portal(master, tb, master, eid, topo,
     1766                            tbparams)
     1767                    self.add_control_portal(tb, master, master, eid, topo,
     1768                            tbparams)
    15231769
    15241770        # Connect the portal nodes into the topologies and clear out
     
    17151961            top = topdl.topology_from_xml(file=split_data, top="experiment")
    17161962
    1717             hosts = self.allocate_ips_to_topo(top)
     1963            hosts, ip_allocator = self.allocate_ips_to_topo(top)
    17181964             # Find the testbeds to look up
    17191965            testbeds = set([ a.value for e in top.elements \
     
    17592005                    self.auth.set_attribute(asignee, "%s/%s" % (configpath, f))
    17602006
    1761             self.add_portals(top, topo, eid, master, tbparams)
     2007            self.add_portals(top, topo, eid, master, tbparams, ip_allocator)
     2008            # Now get access to the dynamic testbeds
     2009            for k, t in topo.items():
     2010                if not t.get_attribute('dynamic'):
     2011                    continue
     2012                tb = t.get_attribute('testbed')
     2013                if tb:
     2014                    self.get_access(tb, None, user, tbparams, master,
     2015                            export_project, access_user)
     2016                    tbparams[k] = tbparams[tb]
     2017                    del tbparams[tb]
     2018                    allocated[k] = 1
     2019                else:
     2020                    raise service_error(service_error.internal,
     2021                            "Dynamic allocation from no testbed!?")
     2022
    17622023            self.wrangle_software(expid, top, topo, tbparams)
    17632024
     
    17692030                tbparams[k]['federant'] = {\
    17702031                        'name': [ { 'localname' : eid} ],\
    1771                         'emulab': tbparams[k]['emulab'],\
    17722032                        'allocID' : tbparams[k]['allocID'],\
    17732033                        'master' : k == master,\
    17742034                    }
     2035                if tbparams[k].has_key('emulab'):
     2036                        tbparams[k]['federant']['emulab'] = \
     2037                                tbparams[k]['emulab']
    17752038
    17762039            self.state_lock.acquire()
     
    20192282            if rv.has_key('federant'): del rv['federant']
    20202283        else:
    2021             # remove the allocationID info from each federant
     2284            # remove the allocationID and uri info from each federant
    20222285            for f in rv.get('federant', []):
    20232286                if f.has_key('allocID'): del f['allocID']
     2287                if f.has_key('uri'): del f['uri']
    20242288        return rv
    20252289
     
    21562420            for fed in fed_exp.get('federant', []):
    21572421                try:
    2158                     tb = fed['emulab']['project']['testbed']['localname']
     2422                    tb = fed['uri']
    21592423                    aid = fed['allocID']
    21602424                except KeyError, e:
  • fedd/federation/topdl.py

    radcbdaf r69692a9  
    2222        elif getattr(a, '__iter__', None): return a
    2323        else: return [ a ]
     24
     25    def remove_attribute(self, key):
     26        to_del = None
     27        attrs = getattr(self, 'attribute', [])
     28        for i, a in enumerate(attrs):
     29            if a.attribute == key:
     30                to_del = i
     31                break
     32       
     33        if to_del: del attrs[i]
    2434
    2535    def get_attribute(self, key):
     
    384394            return e
    385395
    386     def __init__(self, substrates=[], elements=[]):
     396    def __init__(self, substrates=[], elements=[], attribute=[]):
    387397        self.substrates = [ self.init_class(Substrate, s) \
    388398                for s in self.make_list(substrates) ]
    389399        self.elements = [ self.init_element(e) \
    390400                for e in self.make_list(elements) ]
     401        self.attribute = [ self.init_class(Attribute, c) \
     402                for c in self.make_list(attribute) ]
    391403        self.incorporate_elements()
    392404
     
    419431    def clone(self):
    420432        return Topology(substrates=[s.clone() for s in self.substrates],
    421                 elements=[e.clone() for e in self.elements])
     433                elements=[e.clone() for e in self.elements],
     434                attribute=[a.clone() for a in self.attribute])
    422435
    423436
     
    432445        if self.elements:
    433446            rv['elements'] = [ s.to_dict() for s in self.elements ]
     447        if self.attribute:
     448            rv['attribute'] = [ s.to_dict() for s in self.attribute]
    434449        return rv
    435450
     
    519534
    520535        for k in e.keys():
    521             if isinstance(e[k], (basestring, int, float, long)):
     536            if isinstance(e[k], basestring):
    522537                rv += "<%s>%s</%s>" % (k, escape(e[k]), k)
     538            elif isinstance(e[k], (int, float, long)):
     539                rv += "<%s>%d</%s>" % (k, e[k], k)
    523540            elif isinstance(e[k], dict):
    524541                rv += "<%s>%s</%s>" % (k, dict_to_xml(e[k]), k)
     
    530547                        rv += "<%s>%s</%s>" % (k, escape(ee), k)
    531548            else:
    532                 raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
     549                try:
     550                    rv += "<%s>%s</%s>" % (k, e[k], k)
     551                except Exception:
     552                    raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
    533553        if top: rv += "</%s>" % top
    534554        return rv
     
    582602    return t
    583603
    584 def generate_portal_command_filter(cmd):
     604def generate_portal_command_filter(cmd, add_filter=None):
    585605    def rv(e):
    586606        s =""
    587607        if isinstance(e, Computer):
    588608            gw = e.get_attribute('portal')
    589             if gw:
     609            if add_filter and callable(add_filter):
     610                add = add_filter(e)
     611            else:
     612                add = True
     613            if gw and add:
    590614                s = "%s $%s\n" % (cmd, to_tcl_name(e.name[0]))
    591615        return s
Note: See TracChangeset for help on using the changeset viewer.