source: fedd/federation/topdl.py @ 97edf0d

axis_examplecompt_changesinfo-opsversion-3.01version-3.02
Last change on this file since 97edf0d was d46b1d5, checked in by Ted Faber <faber@…>, 15 years ago

Bracked all tcl names so that names with a dash (and other atrocities) will
work. Also switch to manual routing by default in tcl/ns2 output.

  • Property mode set to 100644
File size: 23.0 KB
Line 
1#!/usr/local/bin/python
2
3import re
4
5class base:
6    @staticmethod
7    def init_class(c, arg):
8        if isinstance(arg, dict):
9            try:
10                return c(**arg)
11            except:
12                print "%s" % arg
13                raise
14        elif isinstance(arg, c):
15            return arg
16        else:
17            return None
18
19    @staticmethod
20    def make_list(a):
21        if isinstance(a, basestring) or isinstance(a, dict): return [ a ]
22        elif getattr(a, '__iter__', None): return a
23        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]
34
35    def get_attribute(self, key):
36        rv = None
37        attrs = getattr(self, 'attribute', None)
38        if attrs:
39            for a in attrs:
40                if a.attribute == key:
41                    rv = a.value
42                    break
43        return rv
44
45    def set_attribute(self, key, value):
46        attrs = getattr(self, 'attribute', None)
47        if attrs is None:
48            return
49        for a in attrs:
50            if a.attribute == key: 
51                a.value = value
52                break
53        else:
54            attrs.append(Attribute(key, value))
55
56class ConsistencyError(RuntimeError): pass
57class NamespaceError(RuntimeError): pass
58
59class Attribute(base):
60    def __init__(self, attribute, value):
61        self.attribute = attribute
62        self.value = value
63
64    def clone(self):
65        return Attribute(attribute=self.attribute, value=self.value)
66
67    def to_dict(self):
68        return { 'attribute': self.attribute, 'value': self.value }
69
70class Capacity(base):
71    def __init__(self, rate, kind):
72        self.rate = float(rate)
73        self.kind = kind
74
75    def clone(self):
76        return Capacity(rate=self.rate, kind=self.kind)
77
78    def to_dict(self):
79        return { 'rate': float(self.rate), 'kind': self.kind }
80
81class Latency(base):
82    def __init__(self, time, kind):
83        self.time = float(time)
84        self.kind = kind
85
86    def clone(self):
87        return Latency(time=self.time, kind=self.kind)
88
89    def to_dict(self):
90        return { 'time': float(self.time), 'kind': self.kind }
91
92class Substrate(base):
93    def __init__(self, name, capacity=None, latency=None, attribute=[]):
94        self.name = name
95        self.capacity = self.init_class(Capacity, capacity)
96        self.latency = self.init_class(Latency, latency)
97        self.attribute = [ self.init_class(Attribute, a) \
98                for a in self.make_list(attribute) ]
99        self.interfaces = [ ]
100
101    def clone(self):
102        if self.capacity: c = self.capacity.clone()
103        else: c = None
104
105        if self.latency: l = self.latency.clone()
106        else: l = None
107
108        return Substrate(name=self.name,
109                capacity=c,
110                latency=l,
111                attribute = [a.clone() for a in self.attribute])
112
113    def to_dict(self):
114        rv = { 'name': self.name }
115        if self.capacity:
116            rv['capacity'] = self.capacity.to_dict()
117        if self.latency:
118            rv['latency'] = self.latency.to_dict()
119        if self.attribute:
120            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
121        return rv
122
123class CPU(base):
124    def __init__(self, type, attribute=[]):
125        self.type = type
126        self.attribute = [ self.init_class(Attribute, a) for a in \
127                self.make_list(attribute) ]
128
129    def clone(self):
130        return CPU(type=self.type,
131                attribute = [a.clone() for a in self.attribute])
132
133    def to_dict(self):
134        rv = { 'type': self.type}
135        if self.attribute:
136            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
137        return rv
138
139class Storage(base):
140    def __init__(self, amount, persistence, attribute=[]):
141        self.amount = float(amount)
142        self.presistence = persistence
143        self.attribute = [ self.init_class(Attribute, a) \
144                for a in self.make_list(attribute) ]
145
146    def clone(self):
147        return Storage(amount=self.amount, persistence=self.persistence, 
148                attribute = [a.clone() for a in self.attribute])
149
150    def to_dict(self):
151        rv = { 'amount': float(self.amount), 'persistence': self.persistence }
152        if self.attribute:
153            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
154        return rv
155
156class OperatingSystem(base):
157    def __init__(self, name=None, version=None, distribution=None,
158            distributionversion=None, attribute=[]):
159        self.name = name
160        self.version = version
161        self.distribution = distribution
162        self.distributionversion = distributionversion
163        self.attribute = [ self.init_class(Attribute, a) \
164                for a in self.make_list(attribute) ]
165
166    def clone(self):
167        return OperatingSystem(name=self.name,
168                version=self.version,
169                distribution=self.distribution,
170                distributionversion=self.distributionversion,
171                attribute = [ a.clone() for a in self.attribute])
172
173    def to_dict(self):
174        rv = { }
175        if self.name: rv['name'] = self.name
176        if self.version: rv['version'] = self.version
177        if self.distribution: rv['version'] = self.distribution
178        if self.distributionversion: rv['version'] = self.distributionversion
179        if self.attribute:
180            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
181        return rv
182
183class Software(base):
184    def __init__(self, location, install=None, attribute=[]):
185        self.location = location
186        self.install = install
187        self.attribute = [ self.init_class(Attribute, a)\
188                for a in self.make_list(attribute) ]
189
190    def clone(self):
191        return Software(location=self.location, install=self.install, 
192                attribute=[a.clone() for a in self.attribute])
193
194    def to_dict(self):
195        rv = { 'location': self.location }
196        if self.install: rv['install'] = self.install
197        if self.attribute:
198            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
199        return rv
200
201class Interface(base):
202    def __init__(self, substrate, name=None, capacity=None, latency=None,
203            attribute=[], element=None):
204        self.name = name
205        self.substrate = self.make_list(substrate)
206        self.capacity = self.init_class(Capacity, capacity)
207        self.latency = self.init_class(Latency, latency)
208        self.attribute = [ self.init_class(Attribute, a) \
209                for a in self.make_list(attribute) ]
210        self.element = element
211        self.subs = [ ]
212
213    def clone(self):
214        if self.capacity: c = self.capacity.clone()
215        else: c = None
216
217        if self.latency: l = self.latency.clone()
218        else: l = None
219
220        return Interface(substrate=self.substrate, name=self.name,
221                capacity=c, latency=l,
222                attribute = [ a.clone() for a in self.attribute])
223
224    def to_dict(self):
225        rv = { 'substrate': self.substrate, 'name': self.name }
226        if self.capacity:
227            rv['capacity'] = self.capacity.to_dict()
228        if self.latency:
229            rv['latency'] = self.latency.to_dict()
230        if self.attribute:
231            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
232        return rv
233
234class ID(base):
235    def __init__(self, fedid=None, uuid=None, uri=None, localname=None,
236            kerberosUsername=None):
237        self.fedid=fedid
238        self.uuid = uuid
239        self.uri = uri
240        self.localname = localname
241        self.kerberosUsername = kerberosUsername
242
243    def clone(self):
244        return ID(self.fedid, self.uuid, self.uri, self.localname,
245                self.kerberosUsername)
246
247    def to_dict(self):
248        rv = { }
249        if self.fedid: rv['fedid'] = self.fedid
250        if self.uuid: rv['uuid'] = self.uuid
251        if self.uri: rv['uri'] = self.uri
252        if self.localname: rv['localname'] = self.localname
253        if self.kerberosUsername: rv['kerberosUsername'] = self.kerberosUsername
254        return rv
255
256class Computer(base):
257    def __init__(self, name=[], cpu=[], os=[], software=[], storage=[],
258            interface=[], attribute=[]):
259        def assign_element(i):
260            i.element = self
261
262        self.name = self.make_list(name)
263        self.cpu = [ self.init_class(CPU, c)  for c in self.make_list(cpu) ]
264        self.os = [ self.init_class(OperatingSystem, c) \
265                for c in self.make_list(os) ]
266        self.software = [ self.init_class(Software, c) \
267                for c in self.make_list(software) ]
268        self.storage = [ self.init_class(Storage, c) \
269                for c in self.make_list(storage) ]
270        self.interface = [ self.init_class(Interface, c) \
271                for c in self.make_list(interface) ]
272        self.attribute = [ self.init_class(Attribute, a) \
273                for a in self.make_list(attribute) ]
274        map(assign_element, self.interface)
275
276    def clone(self):
277        return Computer(name=self.name,
278                cpu=[x.clone() for x in self.cpu],
279                os=[x.clone() for x in self.os],
280                software=[x.clone() for x in self.software],
281                storage=[x.clone() for x in self.storage],
282                interface=[x.clone() for x in self.interface],
283                attribute=[x.clone() for x in self.attribute])
284
285    def to_dict(self):
286        rv = { }
287        if self.name:
288            rv['name'] = self.name
289        if self.cpu:
290            rv['cpu'] = [ c.to_dict() for  c in self.cpu ]
291        if self.os:
292            rv['os'] = [ o.to_dict() for o in self.os ]
293        if self.software:
294            rv['software'] = [ s.to_dict() for s in self.software ]
295        if self.storage:
296            rv['storage'] = [ s.to_dict for s in self.storage ]
297        if self.interface:
298            rv['interface'] = [ i.to_dict() for i in self.interface ]
299        if self.attribute:
300            rv['attribute'] = [ i.to_dict() for i in self.attribute ]
301        return { 'computer': rv }
302
303
304class Testbed(base):
305    def __init__(self, uri, type, interface=[], attribute=[]):
306        self.uri = uri
307        self.type = type
308        self.interface = [ self.init_class(Interface, c) \
309                for c in self.make_list(interface) ]
310        self.attribute = [ self.init_class(Attribute, c) \
311                for c in self.make_list(attribute) ]
312
313    def clone(self):
314        return Testbed(self.uri, self.type,
315                interface=[i.clone() for i in self.interface],
316                attribute=[a.cone() for a in self.attribute])
317
318    def to_dict(self):
319        rv = { }
320        if self.uri: rv['uri'] = self.uri
321        if self.type: rv['type'] = self.type
322        if self.interface:
323            rv['interface'] = [ i.to_dict() for i in self.interface]
324        if self.attribute:
325            rv['attribute'] = [ a.to_dict() for a in self.attribute]
326        return { 'testbed': rv }
327
328class Segment(base):
329    def __init__(self, id, type, uri, interface=[], attribute=[]):
330        self.id = self.init_class(ID, id)
331        self.type = type
332        self.uri = uri
333        self.interface = [ self.init_class(Interface, c) \
334                for c in self.make_list(interface) ]
335        self.attribute = [ self.init_class(Attribute, c) \
336                for c in self.make_list(attribute) ]
337
338    def clone(self):
339        return Segment(self.id.clone(), self.type, self.uri, 
340                interface=[i.clone() for i in self.interface], 
341                attribute=[a.clone() for a in self.attribute])
342
343    def to_dict(self):
344        rv = { }
345        if self.id: rv['id'] = self.id.to_dict()
346        if self.type: rv['type'] = self.type
347        if self.uri: rv['uri'] = self.uri
348        if self.interface:
349            rv['interface'] = [ i.to_dict() for i in self.interface ]
350        if self.attribute:
351            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
352        return { 'segment': rv }
353
354
355class Other(base):
356    def __init__(self, interface=[], attribute=[]):
357        self.interface = [ self.init_class(Interface, c) \
358                for c in self.make_list(interface) ]
359        self.attribute = [ self.init_class(Attribute, c) \
360                for c in self.make_list(attribute) ]
361
362    def clone(self):
363        return Other(interface=[i.clone() for i in self.interface], 
364                attribute=[a.clone() for a in attribute])
365
366    def to_dict(self):
367        rv = {}
368        if self.interface:
369            rv['interface'] = [ i.to_dict() for i in self.interface ]
370        if self.attribute:
371            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
372        return {'other': rv }
373
374
375class Topology(base):
376    @staticmethod
377    def init_element(e):
378        """
379        e should be of the form { typename: args } where args is a dict full of
380        the right parameters to initialize the element.  e should have only one
381        key, but we walk e's keys in an arbitrary order and instantiate the
382        first key we know how to.
383        """
384        classmap = {
385                'computer': Computer,
386                'testbed': Testbed,
387                'segment': Segment,
388                'other': Other,
389            }
390
391        if isinstance(e, dict):
392            for k in e.keys():
393                cl = classmap.get(k, None)
394                if cl: return cl(**e[k])
395        else:
396            return e
397
398    def __init__(self, substrates=[], elements=[], attribute=[]):
399        self.substrates = [ self.init_class(Substrate, s) \
400                for s in self.make_list(substrates) ]
401        self.elements = [ self.init_element(e) \
402                for e in self.make_list(elements) ]
403        self.attribute = [ self.init_class(Attribute, c) \
404                for c in self.make_list(attribute) ]
405        self.incorporate_elements()
406
407    @staticmethod
408    def name_element_interfaces(e):
409        names = set([i.name for i in e.interface if i.name])
410        inum = 0
411        for i in [ i for i in e.interface if not i.name]:
412            while inum < 1000:
413                n = "inf%03d" % inum
414                inum += 1
415                if n not in names:
416                    i.name = n
417                    break
418            else:
419                raise NamespaceError("Cannot make new interface name")
420
421
422
423    def name_interfaces(self):
424        """
425        For any interface without a name attribute, assign a unique one within
426        its element.
427        """
428
429        for e in self.elements:
430            self.name_element_interfaces(e)
431
432
433    def incorporate_elements(self):
434
435        # Could to this init in one gulp, but we want to look for duplicate
436        # substrate names
437        substrate_map = { }
438        for s in self.substrates:
439            s.interfaces = [ ]
440            if not substrate_map.has_key(s.name):
441                substrate_map[s.name] = s
442            else:
443                raise ConsistencyError("Duplicate substrate name %s" % s.name)
444
445        for e in self.elements:
446            self.name_element_interfaces(e)
447            for i in e.interface:
448                i.element = e
449                i.subs = [ ]
450                for sn in i.substrate:
451                    # NB, interfaces have substrate names in their substrate
452                    # attribute.
453                    if substrate_map.has_key(sn):
454                        sub = substrate_map[sn]
455                        i.subs.append(sub)
456                        sub.interfaces.append(i)
457                    else:
458                        raise ConsistencyError("No such substrate for %s" % sn)
459
460    def clone(self):
461        return Topology(substrates=[s.clone() for s in self.substrates], 
462                elements=[e.clone() for e in self.elements],
463                attribute=[a.clone() for a in self.attribute])
464
465
466    def make_indices(self):
467        sub_index = dict([(s.name, s) for s in self.substrates])
468        elem_index = dict([(n, e) for e in self.elements for n in e.name])
469
470    def to_dict(self):
471        rv = { }
472        if self.substrates:
473            rv['substrates'] = [ s.to_dict() for s in self.substrates ]
474        if self.elements:
475            rv['elements'] = [ s.to_dict() for s in self.elements ]
476        if self.attribute:
477            rv['attribute'] = [ s.to_dict() for s in self.attribute]
478        return rv
479
480def topology_from_xml(string=None, file=None, filename=None, top="topology"):
481    import xml.parsers.expat
482
483    class parser:
484        def __init__(self):
485            self.stack = [ ]
486            self.chars = ""
487            self.key = ""
488            self.have_chars = False
489            self.current = { }
490            self.in_cdata = False
491       
492        def start_element(self, name, attrs):
493            self.chars = ""
494            self.have_chars = False
495            self.key = str(name)
496            self.stack.append((self.current, self.key))
497            self.current = { }
498
499        def end_element(self, name):
500            if self.have_chars:
501                self.chars = self.chars.strip()
502                if len(self.chars) >0:
503                    addit = self.chars
504                else:
505                    addit = self.current
506            else:
507                addit = self.current
508
509            parent, key = self.stack.pop()
510            if parent.has_key(key):
511                if isinstance(parent[key], list):
512                    parent[key].append(addit)
513                else:
514                    parent[key] = [parent[key], addit]
515            else:
516                parent[key] = addit
517            self.current = parent
518            self.key = key
519
520            self.chars = ""
521            self.have_chars = False
522
523        def char_data(self, data):
524            self.have_chars = True
525            self.chars += data
526
527    p = parser()
528    xp = xml.parsers.expat.ParserCreate()
529
530    xp.StartElementHandler = p.start_element
531    xp.EndElementHandler = p.end_element
532    xp.CharacterDataHandler = p.char_data
533
534    num_set = len([ x for x in (string, filename, file)\
535            if x is not None ])
536
537    if num_set != 1:
538        raise RuntimeError("Exactly one one of file, filename and string " + \
539                "must be set")
540    elif filename:
541        f = open(filename, "r")
542        xp.ParseFile(f)
543        f.close()
544    elif file:
545        xp.ParseFile(file)
546    elif string:
547        xp.Parse(string, isfinal=True)
548    else:
549        return None
550
551    return Topology(**p.current[top])
552
553def topology_to_xml(t, top=None):
554    """
555    Print the topology as XML.  This is quick and dirty, but should work for
556    many purposes.  Convert the topology to a dict and print it recursively.
557    """
558    from xml.sax.saxutils import escape
559
560    def dict_to_xml(e, top=None):
561        if top: rv = "<%s>" % top
562        else: rv = ""
563
564        for k in e.keys():
565            if isinstance(e[k], basestring):
566                rv += "<%s>%s</%s>" % (k, escape(e[k]), k)
567            elif isinstance(e[k], (int, float, long)):
568                rv += "<%s>%d</%s>" % (k, e[k], k)
569            elif isinstance(e[k], dict):
570                rv += "<%s>%s</%s>" % (k, dict_to_xml(e[k]), k)
571            elif getattr(e[k], '__iter__', None):
572                for ee in e[k]:
573                    if isinstance(ee, dict):
574                        rv += "<%s>%s</%s>" % (k, dict_to_xml(ee), k)
575                    else:
576                        rv += "<%s>%s</%s>" % (k, escape(ee), k)
577            else:
578                try:
579                    rv += "<%s>%s</%s>" % (k, e[k], k)
580                except Exception:
581                    raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
582        if top: rv += "</%s>" % top
583        return rv
584
585    return dict_to_xml(t.to_dict(), top)
586
587
588def topology_to_vtopo(t):
589    nodes = [ ]
590    lans = [ ]
591
592    for eidx, e in enumerate(t.elements):
593        if e.name: name = e.name[0]
594        else: name = "unnamed_node%d" % eidx
595       
596        ips = [ ]
597        for idx, i in enumerate(e.interface):
598            ip = i.get_attribute('ip4_address')
599            ips.append(ip)
600            port = "%s:%d" % (name, idx)
601            for idx, s in enumerate(i.subs):
602                bw = 100000
603                delay = 0.0
604                if s.capacity:
605                    bw = s.capacity.rate
606                if i.capacity:
607                    bw = i.capacity.rate
608
609                if s.latency:
610                    delay = s.latency.time
611                if i.latency:
612                    bw = i.latency.time
613
614                lans.append({
615                    'member': port,
616                    'vname': s.name,
617                    'ip': ip,
618                    'vnode': name,
619                    'delay': delay,
620                    'bandwidth': bw,
621                    })
622        nodes.append({
623            'ips': ":".join(ips),
624            'vname': name,
625            })
626
627    return { 'node': nodes, 'lan': lans }
628
629def to_tcl_name(n):
630    t = re.sub('-(\d+)', '(\1)', n)
631    return t
632
633def generate_portal_command_filter(cmd, add_filter=None):
634    def rv(e):
635        s =""
636        if isinstance(e, Computer):
637            gw = e.get_attribute('portal')
638            if add_filter and callable(add_filter):
639                add = add_filter(e)
640            else:
641                add = True
642            if gw and add:
643                s = "%s ${%s}\n" % (cmd, to_tcl_name(e.name[0]))
644        return s
645    return rv
646
647def generate_portal_image_filter(image):
648    def rv(e):
649        s =""
650        if isinstance(e, Computer):
651            gw = e.get_attribute('portal')
652            if gw:
653                s = "tb-set-node-os ${%s} %s\n" % (to_tcl_name(e.name[0]), image)
654        return s
655    return rv
656
657def generate_portal_hardware_filter(type):
658    def rv(e):
659        s =""
660        if isinstance(e, Computer):
661            gw = e.get_attribute('portal')
662            if gw:
663                s = "tb-set-hardware ${%s} %s\n" % (to_tcl_name(e.name[0]), type)
664        return s
665    return rv
666
667
668def topology_to_ns2(t, filters=[], routing="Manual"):
669    out = """
670set ns [new Simulator]
671source tb_compat.tcl
672
673"""
674
675    for e in t.elements:
676        rpms = ""
677        tarfiles = ""
678        if isinstance(e, Computer):
679            name = to_tcl_name(e.name[0])
680            out += "set %s [$ns node]\n" % name
681            if e.os and len(e.os) == 1:
682                osid = e.os[0].get_attribute('osid')
683                if osid:
684                    out += "tb-set-node-os ${%s} %s\n" % (name, osid)
685            hw = e.get_attribute('type')
686            if hw:
687                out += "tb-set-hardware ${%s} %s\n" % (name, hw)
688            for s in e.software:
689                if s.install:
690                    tarfiles += "%s %s " % (s.install, s.location)
691                else:
692                    rpms += "%s " % s.location
693            if rpms:
694                out += "tb-set-node-rpms ${%s} %s\n" % (name, rpms)
695            if tarfiles:
696                out += "tb-set-node-tarfiles ${%s} %s\n" % (name, tarfiles)
697            startcmd = e.get_attribute('startup')
698            if startcmd:
699                out+= 'tb-set-node-startcmd ${%s} "%s"\n' % (name, startcmd)
700            for f in filters:
701                out += f(e)
702            out+= "\n"
703   
704    for idx, s in enumerate(t.substrates):
705        loss = s.get_attribute('loss')
706        if s.latency:
707            delay = s.latency.time
708        else:
709            delay = 0
710        name = to_tcl_name(s.name or "sub%d" % idx)
711
712        if len(s.interfaces) > 2:
713            # Lan
714            members = [ to_tcl_name("${%s}") % i.element.name[0] \
715                    for i in s.interfaces]
716            out += 'set %s [$ns make-lan "%s" %fkb %fms ]\n' % \
717                    (name, " ".join(members), s.capacity.rate, delay)
718            if loss:
719                "tb-set-lan-loss ${%s} %f\n" % (name, float(loss))
720
721            for i in s.interfaces:
722                e = i.element
723                ip = i.get_attribute("ip4_address")
724                if ip:
725                    out += "tb-set-ip-lan ${%s} ${%s} %s\n" % \
726                            (to_tcl_name(e.name[0]), name, ip)
727                if i.capacity and i.capacity.rate != s.capacity.rate:
728                    out += "tb-set-node-lan-bandwidth ${%s} ${%s} %fkb\n" % \
729                            (to_tcl_name(e.name[0]), name, i.capacity.rate)
730                if i.latency and i.latency.time != delay:
731                    out += "tb-set-node-lan-delay ${%s} ${%s} %fms\n" % \
732                            (to_tcl_name(e.name[0]), name, i.latency.time)
733                iloss = i.get_attribute('loss')
734                if loss and iloss != loss :
735                    out += "tb-set-node-lan-loss ${%s} ${%s} %f\n" % \
736                            (to_tcl_name(e.name[0]), name, float(loss))
737            out+= "\n"
738        elif len(s.interfaces) == 2:
739            f = s.interfaces[0]
740            t = s.interfaces[1]
741
742            out += "set %s [$ns duplex-link ${%s} ${%s} %fkb %fms DropTail]\n" %\
743                    (name, to_tcl_name(f.element.name[0]), 
744                            to_tcl_name(t.element.name[0]),
745                            s.capacity.rate, delay)
746            if loss:
747                out += "tb-set-link-loss ${%s} %f\n" % (name, float(loss))
748
749            for i in s.interfaces:
750                lloss = i.get_attribute("loss")
751                cap_override = i.capacity and \
752                        i.capacity.rate != s.capacity.rate
753                delay_override = i.latency and \
754                        i.latency.time != delay
755                loss_override = lloss and lloss != loss
756                if cap_override or delay_override or loss_override:
757                    if i.capacity: cap = i.capacity.rate
758                    else: cap = s.capacity.rate
759
760                    if i.latency: delay = i.latency.time
761
762                    if lloss: loss = lloss
763                    else: loss = loss or 0.0
764
765                    out += "tb-set-link-simplex-params ${%s} ${%s} %fms %fkb %f\n"\
766                            % (name, to_tcl_name(i.element.name[0]),
767                                    delay, cap, loss)
768                ip = i.get_attribute('ip4_address')
769                if ip:
770                    out += "tb-set-ip-link ${%s} ${%s} %s\n" % \
771                            (to_tcl_name(i.element.name[0]), name, ip)
772            out+= "\n"
773        for f in filters:
774            out+= f(s)
775    out+="$ns rtproto %s" % routing
776    out+="""
777$ns run
778"""
779    return out
780
781def topology_to_rspec(t, filters=[]):
782    out = '<?xml version="1.0" encoding="UTF-8"?>\n' + \
783        '<rspec xmlns="http://www.protogeni.net/resources/rspec/0.1"\n' + \
784        '\txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + \
785        '\txsi:schemaLocation="http://www.protogeni.net/resources/rspec/0.1 '+ \
786        'http://www.protogeni.net/resources/rspec/0.1/request.xsd"\n' + \
787        '\ttype="request" >\n'
788
789    ifname = { }
790    ifnode = { }
791
792    for e in [e for e in t.elements if isinstance(e, Computer)]:
793        name = e.name[0]
794        virt_type = e.get_attribute("virtualization_type") or "emulab-vnode"
795        exclusive = e.get_attribute("exclusive") or "1"
796        hw = e.get_attribute("type") or "pc";
797        slots = e.get_attribute("slots") or "1";
798        startup = e.get_attribute("startup")
799        # XXX: unreliable on ProtoGENI 20100303
800        #tarfiles = " ".join([ "%s %s" % (s.install, s.location) \
801        #       for s in e.software if s.location and s.install ])
802
803        extras = ""
804        if startup: extras += '\t\tstartup_command="%s"\n' % startup
805        #if tarfiles: extras +='\t\ttarfiles="%s"\n' % tarfiles
806        out += '\t<node virtual_id="%s"\n\t\tvirtualization_type="%s"\n' % \
807                (name, virt_type)
808        out += '\t\texclusive="%s"' % exclusive
809        if extras: out += '\n%s' % extras
810        out += '>\n'
811        out += '\t\t<node_type type_name="%s" slots="%s"/>\n' % (hw, slots)
812        for i, ii in enumerate(e.interface):
813            out += '\t\t<interface virtual_id="%s"/>\n' % ii.name
814            ifnode[ii] = name
815        for f in filters:
816            out += f(s)
817        out += '\t</node>\n'
818
819    for i, s in enumerate(t.substrates):
820        if len(s.interfaces) == 0: 
821            continue
822        out += '\t<link virtual_id="%s" link_type="ethernet">\n' % s.name
823        if s.capacity and s.capacity.kind == "max":
824            bwout = True
825            out += '\t\t<bandwidth>%d</bandwidth>\n' % s.capacity.rate
826        else:
827            bwout = False
828        if s.latency and s.latency.kind == "max":
829            out += '\t\t<latency>%d</latency>\n' % s.latency.time
830        elif bwout:
831            out += '\t\t<latency>0</latency>\n'
832        for ii in s.interfaces:
833            out += ('\t\t<interface_ref virtual_node_id="%s" ' + \
834                    'virtual_interface_id="%s"/>\n') % (ifnode[ii], ii.name)
835        for f in filters:
836            out += f(s)
837        out += '\t</link>\n'
838    out += '</rspec>\n'
839    return out
840
Note: See TracBrowser for help on using the repository browser.