source: fedd/federation/topdl.py @ 835cf55

axis_examplecompt_changesinfo-ops
Last change on this file since 835cf55 was 8aaf8f8, checked in by Ted Faber <faber@…>, 14 years ago

Remove an unexercised filter bug and clean up some debugging code that was
commented out and not removed.

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