Changeset b4b19c7


Ignore:
Timestamp:
Apr 21, 2010 5:31:03 AM (15 years ago)
Author:
Ted Faber <faber@…>
Branches:
axis_example, compt_changes, info-ops, master, version-3.01, version-3.02
Children:
f7a54c6
Parents:
f54e8e4
Message:

Get topology information into the info operation, as annotations of a topology description. This required adding such information to the start segment replies as well

Location:
fedd
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • fedd/fedd_client.py

    rf54e8e4 rb4b19c7  
    134134        self.add_option("--data", dest="data", default=[],
    135135                action="append", type="choice",
    136                 choices=("id", "federant", "vtopo", "vis", "log", "status"),
     136                choices=("id", "experimentdescription", "federant", "vtopo",
     137                    "vis", "log", "status"),
    137138                help="data to extract")
    138139
     
    360361        # called.
    361362        self.params = {
    362                 'vis': ('vis', self.print_xml('vis')),
    363                 'vtopo': ('vtopo', self.print_xml('vtopo')),
     363                'vis': ('vis', self.print_vis_or_vtopo('vis')),
     364                'vtopo': ('vtopo', self.print_vis_or_vtopo('vtopo')),
    364365                'federant': ('federant', self.print_xml),
     366                'experimentdescription': \
     367                        ('experimentdescription', self.print_xml),
    365368                'id': ('experimentID', self.print_id),
    366369                'status': ('experimentStatus', self.print_string),
     
    379382                    print >>out, "%s: %s" % (k, id[k])
    380383
    381     class print_xml:
     384    def print_xml(self, d, out=sys.stdout):
     385        """
     386        Very simple ugly xml formatter of the kinds of dicts that come back
     387        from services.
     388        """
     389        if isinstance(d, dict):
     390            for k, v in d.items():
     391                print >>out, "<%s>" % k
     392                self.print_xml(v, out)
     393                print >>out, "</%s>" % k
     394        elif isinstance(d, list):
     395            for x in d:
     396                self.print_xml(x, out)
     397        else:
     398            print >>out, d
     399
     400
     401    class print_vis_or_vtopo:
    382402        """
    383403        Print the retrieved data is a simple xml representation of the dict.
  • fedd/federation/emulab_access.py

    rf54e8e4 rb4b19c7  
    15521552                    debug=self.create_debug, log=alloc_log)
    15531553            rv = starter(self, ename, proj, user, expfile, tmpdir)
     1554            # Copy the assigned names into the return topology
     1555            rvtopo = topo.clone()
     1556            for e in [ e for e in rvtopo.elements \
     1557                   if isinstance(e, topdl.Computer)]:
     1558                for n in e.name:
     1559                    if n in starter.node:
     1560                        e.set_attribute('hostname', starter.node[n])
    15541561        except service_error, e:
    15551562            err = e
     
    15811588                    'allocationLog': logv,
    15821589                    }
    1583             retval = self.allocation[aid]['started']
     1590            retval = copy.copy(self.allocation[aid]['started'])
    15841591            self.write_state()
    15851592            self.state_lock.release()
    1586 
     1593            retval['segmentdescription'] =  \
     1594                    { 'topdldescription': rvtopo.to_dict() }
    15871595            return retval
    15881596        elif err:
  • fedd/federation/experiment_control.py

    rf54e8e4 rb4b19c7  
    10071007            self.log_collector = log_collector
    10081008            self.response = None
     1009            self.node = { }
     1010
     1011        def make_map(self, resp):
     1012            if 'segmentdescription' in resp and \
     1013                    'topdldescription' in resp['segmentdescription']:
     1014                top = topdl.Topology(\
     1015                        **resp['segmentdescription']['topdldescription'])
     1016                for e in [e for e in top.elements \
     1017                        if isinstance(e, topdl.Computer)]:
     1018                    hn = e.get_attribute('hostname')
     1019                    if hn:
     1020                        for n in e.name:
     1021                            self.node[n] = hn
    10091022
    10101023        def __call__(self, uri, aid, topo, masters, attrs=None, connInfo=None):
     
    10501063                        for line in  lval.splitlines(True):
    10511064                            self.log_collector.write(line)
     1065                    self.make_map(r['StartSegmentResponseBody'])
    10521066                    self.response = r
    10531067                else:
     
    10881102
    10891103    def allocate_resources(self, allocated, masters, eid, expid,
    1090             tbparams, topo, tmpdir, alloc_log=None, log_collector=None,
     1104            tbparams, top, topo, tmpdir, alloc_log=None, log_collector=None,
    10911105            attrs=None, connInfo={}):
    10921106
     
    11011115        thread_pool = self.thread_pool(self.nthreads)
    11021116        threads = [ ]
     1117        starters = [ ]
    11031118
    11041119        for tb in allocated.keys():
     
    11181133                        "No alloc id for testbed %s !?" % tb)
    11191134
     1135            s = self.start_segment(log=log, debug=self.debug,
     1136                    testbed=tb, cert_file=self.cert_file,
     1137                    cert_pwd=self.cert_pwd, trusted_certs=self.trusted_certs,
     1138                    caller=self.call_StartSegment,
     1139                    log_collector=log_collector)
     1140            starters.append(s)
    11201141            t  = self.pooled_thread(\
    1121                     target=self.start_segment(log=log, debug=self.debug,
    1122                         testbed=tb, cert_file=self.cert_file,
    1123                         cert_pwd=self.cert_pwd,
    1124                         trusted_certs=self.trusted_certs,
    1125                         caller=self.call_StartSegment,
    1126                         log_collector=log_collector),
     1142                    target=s, name=tb,
    11271143                    args=(uri, aid, topo[tb], masters, attrs, connInfo[tb]),
    1128                     name=tb,
    11291144                    pdata=thread_pool, trace_file=self.trace_file)
    11301145            threads.append(t)
     
    11901205                return
    11911206        else:
     1207            # Walk through the successes and gather the virtual to physical
     1208            # mapping.
     1209            node = { }
     1210            for s in starters:
     1211                node.update(s.node)
     1212            # Assigng the mapping as a hostname attribute
     1213            for e in [ e for e in top.elements \
     1214                    if isinstance(e, topdl.Computer)]:
     1215                for n in e.name:
     1216                    if n in node:
     1217                        e.set_attribute('hostname', node[n])
    11921218            log.info("[start_segment]: Experiment %s active" % eid)
    11931219
     
    12051231            log.debug("[start_experiment]: not removing %s" % tmpdir)
    12061232
    1207         # Insert the experiment into our state and update the disk copy
     1233        # Insert the experiment into our state and update the disk copy.
    12081234        self.state_lock.acquire()
    12091235        self.state[expid]['experimentStatus'] = 'active'
    12101236        self.state[eid] = self.state[expid]
     1237        self.state[eid]['experimentdescription']['topdldescription'] = \
     1238                top.to_dict()
    12111239        if self.state_filename: self.write_state()
    12121240        self.state_lock.release()
     
    12281256
    12291257
    1230     def create_experiment_state(self, fid, req, expid, expcert, 
     1258    def create_experiment_state(self, fid, req, expid, expcert,
    12311259            state='starting'):
    12321260        """
     
    16621690                # Add the service to masters
    16631691                for tb in s.get('export', []):
    1664                     if s.get('name', None) and s.get('import', None):
     1692                    if s.get('name', None):
    16651693                        if tb not in masters:
    16661694                            masters[tb] = [ ]
     
    16761704                                params=params))
    16771705                    else:
    1678                         log.error('Testbed service does not have name " + \
     1706                        self.log.error('Testbed service does not have name " + \
    16791707                                "and importers')
    16801708
     
    17611789            self.state[eid]['vtopo'] = vtopo
    17621790            self.state[eid]['vis'] = vis
     1791            self.state[eid]['experimentdescription'] = \
     1792                    { 'topdldescription': top.clone() }
    17631793            self.state[expid]['federant'] = \
    17641794                    [ tbparams[tb]['federant'] for tb in tbparams.keys() \
     
    18331863        t  = Thread(target=self.allocate_resources,
    18341864                args=(allocated, masters, eid, expid, tbparams,
    1835                     topo, tmpdir, alloc_log, alloc_collector, attrs, connInfo),
     1865                    top, topo, tmpdir, alloc_log, alloc_collector, attrs,
     1866                    connInfo),
    18361867                name=eid)
    18371868        t.start()
     
    20112042                if f.has_key('allocID'): del f['allocID']
    20122043                if f.has_key('uri'): del f['uri']
     2044
    20132045        return rv
    20142046
  • fedd/federation/local_emulab_segment.py

    rf54e8e4 rb4b19c7  
    9090$ns run
    9191"""
     92        self.node = { }
    9293
    9394    def get_state(self, pid, eid):
     
    138139            self.log.debug("State is %s" % state)
    139140            return state
     141
     142    def get_mapping(self, pid, eid):
     143        # command to test experiment state
     144        expinfo_exec = "/usr/testbed/bin/expinfo" 
     145        # The expinfo command.
     146        cmd = [ expinfo_exec, '-m', pid, eid]
     147
     148        dev_null = None
     149        try:
     150            dev_null = open("/dev/null", "a")
     151        except IOError, e:
     152            self.log.error("[get_state]: can't open /dev/null: %s" %e)
     153
     154        if self.debug:
     155            rv = 0
     156        else:
     157            self.log.debug("Getting mapping for %s %s" % (pid, eid))
     158            phys_start = re.compile('^Physical\s+Node\s+Mapping')
     159            phys_line = re.compile('(\S+)\s+\S+\s+\S+\s+(.*)')
     160            phys_end = re.compile('^$')
     161            status = subprocess.Popen(cmd, stdout=subprocess.PIPE,
     162                    stderr=dev_null, close_fds=True)
     163
     164            # Parse the info output.  Format:
     165            #
     166            # stuff
     167            # Physical Node Mapping:
     168            # ID              Type         OS              Physical   
     169            # --------------- ------------ --------------- ------------
     170            # virtual         dummy        dummy           physical
     171            #
     172            foundit = False
     173            skip = 0
     174            for line in status.stdout:
     175                if phys_start.match(line):
     176                    skip = 2
     177                    foundit = True
     178                elif not foundit:
     179                    continue
     180                elif skip > 0:
     181                    skip -= 1
     182                elif phys_end.match(line):
     183                    break
     184                else:
     185                    m = phys_line.match(line.strip())
     186                    if m: self.node[m.group(1)] = m.group(2)
     187                    else: self.log.warn(
     188                            "Matching failed while parsing node mapping")
     189            rv = status.wait()
     190
     191        # If the experiment is not present the subcommand returns a
     192        # non-zero return value.  If we successfully parsed a "none"
     193        # outcome, ignore the return code.
     194        if rv != 0 :
     195            raise service_error(service_error.internal,
     196                    "Cannot get node mapping of segment:%s/%s" % (pid, eid))
     197        else:
     198            return True
     199
    140200
    141201
     
    242302                state = self.get_state(pid, eid)
    243303                self.log.debug("[start_segment]: state is %s" % state)
    244                 return state == 'active'
     304                if state != 'active':
     305                    return False
    245306        # Everything has gone OK.
     307        self.get_mapping(pid,eid)
    246308        return True
    247309
  • fedd/federation/protogeni_access.py

    rf54e8e4 rb4b19c7  
    10971097                    "%s/%s" % (self.staging_dir, ename), tmpdir, cf, cpw,
    10981098                    certfile, topo, connInfo, services)
     1099            # Copy the assigned names into the return topology
     1100            rvtopo = topo.clone()
     1101            for e in [ e for e in rvtopo.elements \
     1102                   if isinstance(e, topdl.Computer)]:
     1103                for n in e.name:
     1104                    if n in starter.node:
     1105                        e.set_attribute('hostname', starter.node[n])
    10991106        except service_error, e:
    11001107            err = e
     
    11261133                    'allocationLog': logv,
    11271134                    }
    1128             retval = self.allocation[aid]['started']
     1135            retval = copy.copy(self.allocation[aid]['started'])
    11291136            self.write_state()
     1137            retval['segmentdescription'] =  \
     1138                    { 'topdldescription': rvtopo.to_dict() }
    11301139            self.state_lock.release()
    11311140
  • fedd/federation/proxy_emulab_segment.py

    rf54e8e4 rb4b19c7  
    2525$ns run
    2626"""
     27        self.node = { }
    2728
    2829    def get_state(self, user, host, pid, eid):
     
    7879
    7980
     81    def get_mapping(self, pid, eid):
     82        # command to test experiment state
     83        expinfo_exec = "/usr/testbed/bin/expinfo" 
     84        # The expinfo ssh command.  Note the identity restriction to use
     85        # only the identity provided in the pubkey given.
     86        cmd = [self.ssh_exec, '-o', 'IdentitiesOnly yes', '-o',
     87                'StrictHostKeyChecking no', '-i',
     88                self.ssh_privkey_file, "%s@%s" % (user, host),
     89                expinfo_exec, '-m', pid, eid]
     90
     91        dev_null = None
     92        try:
     93            dev_null = open("/dev/null", "a")
     94        except IOError, e:
     95            self.log.error("[get_state]: can't open /dev/null: %s" %e)
     96
     97        if self.debug:
     98            rv = 0
     99        else:
     100            self.log.debug("Getting mapping for %s %s" % (pid, eid))
     101            phys_start = re.compile('^Physical\s+Node\s+Mapping')
     102            phys_line = re.compile('(\S+)\s+\S+\s+\S+\s+(.*)')
     103            phys_end = re.compile('^$')
     104            status = subprocess.Popen(cmd, stdout=subprocess.PIPE,
     105                    stderr=dev_null, close_fds=True)
     106
     107            # Parse the info output.  Format:
     108            #
     109            # stuff
     110            # Physical Node Mapping:
     111            # ID              Type         OS              Physical   
     112            # --------------- ------------ --------------- ------------
     113            # virtual         dummy        dummy           physical
     114            #
     115            foundit = False
     116            skip = 0
     117            for line in status.stdout:
     118                if phys_start.match(line):
     119                    skip = 2
     120                    foundit = True
     121                elif not foundit:
     122                    continue
     123                elif skip > 0:
     124                    skip -= 1
     125                elif phys_end.match(line):
     126                    break
     127                else:
     128                    m = phys_line.match(line.strip())
     129                    if m: self.node[m.group(1)] = m.group(2)
     130                    else: self.log.warn(
     131                            "Matching failed while parsing node mapping")
     132            rv = status.wait()
     133
     134        # If the experiment is not present the subcommand returns a
     135        # non-zero return value.  If we successfully parsed a "none"
     136        # outcome, ignore the return code.
     137        if rv != 0 :
     138            raise service_error(service_error.internal,
     139                    "Cannot get node mapping of segment:%s/%s" % (pid, eid))
     140        else:
     141            return True
     142
     143
    80144    def __call__(self, parent, eid, pid, user, tclfile, tmpdir, timeout=0):
    81145        """
  • fedd/federation/proxy_protogeni_segment.py

    rf54e8e4 rb4b19c7  
    8686        segment_base.__init__(self, log=log, keyfile=keyfile, debug=debug,
    8787                ch_url=cm_url, sa_url=sa_url, cm_url=cm_url)
     88        self.node = { }
    8889
    8990
     
    131132
    132133        p.Parse(manifest)
     134        # Make the node dict that the callers expect
     135        for k in mp.d:
     136            self.node[k] = mp.d.get('hostname', '')
    133137        return mp.d
    134138
Note: See TracChangeset for help on using the changeset viewer.