source: fedd/federation/topdl.py @ d2471df

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

Some shaky cloning stuff. Can't swear it was a problem, but this should prevent accident connections between list objects during a clone.

  • Property mode set to 100644
File size: 23.1 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=[s for s in 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        # Copy the list of names
278        return Computer(name=[ n for n in self.name ],
279                cpu=[x.clone() for x in self.cpu],
280                os=[x.clone() for x in self.os],
281                software=[x.clone() for x in self.software],
282                storage=[x.clone() for x in self.storage],
283                interface=[x.clone() for x in self.interface],
284                attribute=[x.clone() for x in self.attribute])
285
286    def to_dict(self):
287        rv = { }
288        if self.name:
289            rv['name'] = [ n for n in self.name]
290        if self.cpu:
291            rv['cpu'] = [ c.to_dict() for  c in self.cpu ]
292        if self.os:
293            rv['os'] = [ o.to_dict() for o in self.os ]
294        if self.software:
295            rv['software'] = [ s.to_dict() for s in self.software ]
296        if self.storage:
297            rv['storage'] = [ s.to_dict for s in self.storage ]
298        if self.interface:
299            rv['interface'] = [ i.to_dict() for i in self.interface ]
300        if self.attribute:
301            rv['attribute'] = [ i.to_dict() for i in self.attribute ]
302        return { 'computer': rv }
303
304
305class Testbed(base):
306    def __init__(self, uri, type, interface=[], attribute=[]):
307        self.uri = uri
308        self.type = type
309        self.interface = [ self.init_class(Interface, c) \
310                for c in self.make_list(interface) ]
311        self.attribute = [ self.init_class(Attribute, c) \
312                for c in self.make_list(attribute) ]
313
314    def clone(self):
315        return Testbed(self.uri, self.type,
316                interface=[i.clone() for i in self.interface],
317                attribute=[a.cone() for a in self.attribute])
318
319    def to_dict(self):
320        rv = { }
321        if self.uri: rv['uri'] = self.uri
322        if self.type: rv['type'] = self.type
323        if self.interface:
324            rv['interface'] = [ i.to_dict() for i in self.interface]
325        if self.attribute:
326            rv['attribute'] = [ a.to_dict() for a in self.attribute]
327        return { 'testbed': rv }
328
329class Segment(base):
330    def __init__(self, id, type, uri, interface=[], attribute=[]):
331        self.id = self.init_class(ID, id)
332        self.type = type
333        self.uri = uri
334        self.interface = [ self.init_class(Interface, c) \
335                for c in self.make_list(interface) ]
336        self.attribute = [ self.init_class(Attribute, c) \
337                for c in self.make_list(attribute) ]
338
339    def clone(self):
340        return Segment(self.id.clone(), self.type, self.uri, 
341                interface=[i.clone() for i in self.interface], 
342                attribute=[a.clone() for a in self.attribute])
343
344    def to_dict(self):
345        rv = { }
346        if self.id: rv['id'] = self.id.to_dict()
347        if self.type: rv['type'] = self.type
348        if self.uri: rv['uri'] = self.uri
349        if self.interface:
350            rv['interface'] = [ i.to_dict() for i in self.interface ]
351        if self.attribute:
352            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
353        return { 'segment': rv }
354
355
356class Other(base):
357    def __init__(self, interface=[], attribute=[]):
358        self.interface = [ self.init_class(Interface, c) \
359                for c in self.make_list(interface) ]
360        self.attribute = [ self.init_class(Attribute, c) \
361                for c in self.make_list(attribute) ]
362
363    def clone(self):
364        return Other(interface=[i.clone() for i in self.interface], 
365                attribute=[a.clone() for a in attribute])
366
367    def to_dict(self):
368        rv = {}
369        if self.interface:
370            rv['interface'] = [ i.to_dict() for i in self.interface ]
371        if self.attribute:
372            rv['attribute'] = [ a.to_dict() for a in self.attribute ]
373        return {'other': rv }
374
375
376class Topology(base):
377    @staticmethod
378    def init_element(e):
379        """
380        e should be of the form { typename: args } where args is a dict full of
381        the right parameters to initialize the element.  e should have only one
382        key, but we walk e's keys in an arbitrary order and instantiate the
383        first key we know how to.
384        """
385        classmap = {
386                'computer': Computer,
387                'testbed': Testbed,
388                'segment': Segment,
389                'other': Other,
390            }
391
392        if isinstance(e, dict):
393            for k in e.keys():
394                cl = classmap.get(k, None)
395                if cl: return cl(**e[k])
396        else:
397            return e
398
399    def __init__(self, substrates=[], elements=[], attribute=[]):
400        self.substrates = [ self.init_class(Substrate, s) \
401                for s in self.make_list(substrates) ]
402        self.elements = [ self.init_element(e) \
403                for e in self.make_list(elements) ]
404        self.attribute = [ self.init_class(Attribute, c) \
405                for c in self.make_list(attribute) ]
406        self.incorporate_elements()
407
408    @staticmethod
409    def name_element_interfaces(e):
410        names = set([i.name for i in e.interface if i.name])
411        inum = 0
412        for i in [ i for i in e.interface if not i.name]:
413            while inum < 1000:
414                n = "inf%03d" % inum
415                inum += 1
416                if n not in names:
417                    i.name = n
418                    break
419            else:
420                raise NamespaceError("Cannot make new interface name")
421
422
423
424    def name_interfaces(self):
425        """
426        For any interface without a name attribute, assign a unique one within
427        its element.
428        """
429
430        for e in self.elements:
431            self.name_element_interfaces(e)
432
433
434    def incorporate_elements(self):
435
436        # Could to this init in one gulp, but we want to look for duplicate
437        # substrate names
438        substrate_map = { }
439        for s in self.substrates:
440            s.interfaces = [ ]
441            if not substrate_map.has_key(s.name):
442                substrate_map[s.name] = s
443            else:
444                raise ConsistencyError("Duplicate substrate name %s" % s.name)
445
446        for e in self.elements:
447            self.name_element_interfaces(e)
448            for i in e.interface:
449                i.element = e
450                i.subs = [ ]
451                for sn in i.substrate:
452                    # NB, interfaces have substrate names in their substrate
453                    # attribute.
454                    if substrate_map.has_key(sn):
455                        sub = substrate_map[sn]
456                        i.subs.append(sub)
457                        sub.interfaces.append(i)
458                    else:
459                        raise ConsistencyError("No such substrate for %s" % sn)
460
461    def clone(self):
462        return Topology(substrates=[s.clone() for s in self.substrates], 
463                elements=[e.clone() for e in self.elements],
464                attribute=[a.clone() for a in self.attribute])
465
466
467    def make_indices(self):
468        sub_index = dict([(s.name, s) for s in self.substrates])
469        elem_index = dict([(n, e) for e in self.elements for n in e.name])
470
471    def to_dict(self):
472        rv = { }
473        if self.substrates:
474            rv['substrates'] = [ s.to_dict() for s in self.substrates ]
475        if self.elements:
476            rv['elements'] = [ s.to_dict() for s in self.elements ]
477        if self.attribute:
478            rv['attribute'] = [ s.to_dict() for s in self.attribute]
479        return rv
480
481def topology_from_xml(string=None, file=None, filename=None, top="topology"):
482    import xml.parsers.expat
483
484    class parser:
485        def __init__(self):
486            self.stack = [ ]
487            self.chars = ""
488            self.key = ""
489            self.have_chars = False
490            self.current = { }
491            self.in_cdata = False
492       
493        def start_element(self, name, attrs):
494            self.chars = ""
495            self.have_chars = False
496            self.key = str(name)
497            self.stack.append((self.current, self.key))
498            self.current = { }
499
500        def end_element(self, name):
501            if self.have_chars:
502                self.chars = self.chars.strip()
503                if len(self.chars) >0:
504                    addit = self.chars
505                else:
506                    addit = self.current
507            else:
508                addit = self.current
509
510            parent, key = self.stack.pop()
511            if parent.has_key(key):
512                if isinstance(parent[key], list):
513                    parent[key].append(addit)
514                else:
515                    parent[key] = [parent[key], addit]
516            else:
517                parent[key] = addit
518            self.current = parent
519            self.key = key
520
521            self.chars = ""
522            self.have_chars = False
523
524        def char_data(self, data):
525            self.have_chars = True
526            self.chars += data
527
528    p = parser()
529    xp = xml.parsers.expat.ParserCreate()
530
531    xp.StartElementHandler = p.start_element
532    xp.EndElementHandler = p.end_element
533    xp.CharacterDataHandler = p.char_data
534
535    num_set = len([ x for x in (string, filename, file)\
536            if x is not None ])
537
538    if num_set != 1:
539        raise RuntimeError("Exactly one one of file, filename and string " + \
540                "must be set")
541    elif filename:
542        f = open(filename, "r")
543        xp.ParseFile(f)
544        f.close()
545    elif file:
546        xp.ParseFile(file)
547    elif string:
548        xp.Parse(string, isfinal=True)
549    else:
550        return None
551
552    return Topology(**p.current[top])
553
554def topology_to_xml(t, top=None):
555    """
556    Print the topology as XML.  This is quick and dirty, but should work for
557    many purposes.  Convert the topology to a dict and print it recursively.
558    """
559    from xml.sax.saxutils import escape
560
561    def dict_to_xml(e, top=None):
562        if top: rv = "<%s>" % top
563        else: rv = ""
564
565        for k in e.keys():
566            if isinstance(e[k], basestring):
567                rv += "<%s>%s</%s>" % (k, escape(e[k]), k)
568            elif isinstance(e[k], (int, float, long)):
569                rv += "<%s>%d</%s>" % (k, e[k], k)
570            elif isinstance(e[k], dict):
571                rv += "<%s>%s</%s>" % (k, dict_to_xml(e[k]), k)
572            elif getattr(e[k], '__iter__', None):
573                for ee in e[k]:
574                    if isinstance(ee, dict):
575                        rv += "<%s>%s</%s>" % (k, dict_to_xml(ee), k)
576                    else:
577                        rv += "<%s>%s</%s>" % (k, escape(ee), k)
578            else:
579                try:
580                    rv += "<%s>%s</%s>" % (k, e[k], k)
581                except Exception:
582                    raise ConsistencyError("What is this?? %s %s" % (k, e[k]))
583        if top: rv += "</%s>" % top
584        return rv
585
586    return dict_to_xml(t.to_dict(), top)
587
588
589def topology_to_vtopo(t):
590    nodes = [ ]
591    lans = [ ]
592
593    for eidx, e in enumerate(t.elements):
594        if e.name: name = e.name[0]
595        else: name = "unnamed_node%d" % eidx
596       
597        ips = [ ]
598        for idx, i in enumerate(e.interface):
599            ip = i.get_attribute('ip4_address')
600            ips.append(ip)
601            port = "%s:%d" % (name, idx)
602            for idx, s in enumerate(i.subs):
603                bw = 100000
604                delay = 0.0
605                if s.capacity:
606                    bw = s.capacity.rate
607                if i.capacity:
608                    bw = i.capacity.rate
609
610                if s.latency:
611                    delay = s.latency.time
612                if i.latency:
613                    bw = i.latency.time
614
615                lans.append({
616                    'member': port,
617                    'vname': s.name,
618                    'ip': ip,
619                    'vnode': name,
620                    'delay': delay,
621                    'bandwidth': bw,
622                    })
623        nodes.append({
624            'ips': ":".join(ips),
625            'vname': name,
626            })
627
628    return { 'node': nodes, 'lan': lans }
629
630def to_tcl_name(n):
631    t = re.sub('-(\d+)', '(\1)', n)
632    return t
633
634def generate_portal_command_filter(cmd, add_filter=None):
635    def rv(e):
636        s =""
637        if isinstance(e, Computer):
638            gw = e.get_attribute('portal')
639            if add_filter and callable(add_filter):
640                add = add_filter(e)
641            else:
642                add = True
643            if gw and add:
644                s = "%s ${%s}\n" % (cmd, to_tcl_name(e.name[0]))
645        return s
646    return rv
647
648def generate_portal_image_filter(image):
649    def rv(e):
650        s =""
651        if isinstance(e, Computer):
652            gw = e.get_attribute('portal')
653            if gw:
654                s = "tb-set-node-os ${%s} %s\n" % (to_tcl_name(e.name[0]), image)
655        return s
656    return rv
657
658def generate_portal_hardware_filter(type):
659    def rv(e):
660        s =""
661        if isinstance(e, Computer):
662            gw = e.get_attribute('portal')
663            if gw:
664                s = "tb-set-hardware ${%s} %s\n" % (to_tcl_name(e.name[0]), type)
665        return s
666    return rv
667
668
669def topology_to_ns2(t, filters=[], routing="Manual"):
670    out = """
671set ns [new Simulator]
672source tb_compat.tcl
673
674"""
675
676    for e in t.elements:
677        rpms = ""
678        tarfiles = ""
679        if isinstance(e, Computer):
680            name = to_tcl_name(e.name[0])
681            out += "set %s [$ns node]\n" % name
682            if e.os and len(e.os) == 1:
683                osid = e.os[0].get_attribute('osid')
684                if osid:
685                    out += "tb-set-node-os ${%s} %s\n" % (name, osid)
686            hw = e.get_attribute('type')
687            if hw:
688                out += "tb-set-hardware ${%s} %s\n" % (name, hw)
689            for s in e.software:
690                if s.install:
691                    tarfiles += "%s %s " % (s.install, s.location)
692                else:
693                    rpms += "%s " % s.location
694            if rpms:
695                out += "tb-set-node-rpms ${%s} %s\n" % (name, rpms)
696            if tarfiles:
697                out += "tb-set-node-tarfiles ${%s} %s\n" % (name, tarfiles)
698            startcmd = e.get_attribute('startup')
699            if startcmd:
700                out+= 'tb-set-node-startcmd ${%s} "%s"\n' % (name, startcmd)
701            for f in filters:
702                out += f(e)
703            out+= "\n"
704   
705    for idx, s in enumerate(t.substrates):
706        loss = s.get_attribute('loss')
707        if s.latency:
708            delay = s.latency.time
709        else:
710            delay = 0
711        name = to_tcl_name(s.name or "sub%d" % idx)
712
713        if len(s.interfaces) > 2:
714            # Lan
715            members = [ to_tcl_name("${%s}") % i.element.name[0] \
716                    for i in s.interfaces]
717            out += 'set %s [$ns make-lan "%s" %fkb %fms ]\n' % \
718                    (name, " ".join(members), s.capacity.rate, delay)
719            if loss:
720                "tb-set-lan-loss ${%s} %f\n" % (name, float(loss))
721
722            for i in s.interfaces:
723                e = i.element
724                ip = i.get_attribute("ip4_address")
725                if ip:
726                    out += "tb-set-ip-lan ${%s} ${%s} %s\n" % \
727                            (to_tcl_name(e.name[0]), name, ip)
728                if i.capacity and i.capacity.rate != s.capacity.rate:
729                    out += "tb-set-node-lan-bandwidth ${%s} ${%s} %fkb\n" % \
730                            (to_tcl_name(e.name[0]), name, i.capacity.rate)
731                if i.latency and i.latency.time != delay:
732                    out += "tb-set-node-lan-delay ${%s} ${%s} %fms\n" % \
733                            (to_tcl_name(e.name[0]), name, i.latency.time)
734                iloss = i.get_attribute('loss')
735                if loss and iloss != loss :
736                    out += "tb-set-node-lan-loss ${%s} ${%s} %f\n" % \
737                            (to_tcl_name(e.name[0]), name, float(loss))
738            out+= "\n"
739        elif len(s.interfaces) == 2:
740            f = s.interfaces[0]
741            t = s.interfaces[1]
742
743            out += "set %s [$ns duplex-link ${%s} ${%s} %fkb %fms DropTail]\n" %\
744                    (name, to_tcl_name(f.element.name[0]), 
745                            to_tcl_name(t.element.name[0]),
746                            s.capacity.rate, delay)
747            if loss:
748                out += "tb-set-link-loss ${%s} %f\n" % (name, float(loss))
749
750            for i in s.interfaces:
751                lloss = i.get_attribute("loss")
752                cap_override = i.capacity and \
753                        i.capacity.rate != s.capacity.rate
754                delay_override = i.latency and \
755                        i.latency.time != delay
756                loss_override = lloss and lloss != loss
757                if cap_override or delay_override or loss_override:
758                    if i.capacity: cap = i.capacity.rate
759                    else: cap = s.capacity.rate
760
761                    if i.latency: delay = i.latency.time
762
763                    if lloss: loss = lloss
764                    else: loss = loss or 0.0
765
766                    out += "tb-set-link-simplex-params ${%s} ${%s} %fms %fkb %f\n"\
767                            % (name, to_tcl_name(i.element.name[0]),
768                                    delay, cap, loss)
769                ip = i.get_attribute('ip4_address')
770                if ip:
771                    out += "tb-set-ip-link ${%s} ${%s} %s\n" % \
772                            (to_tcl_name(i.element.name[0]), name, ip)
773            out+= "\n"
774        for f in filters:
775            out+= f(s)
776    out+="$ns rtproto %s" % routing
777    out+="""
778$ns run
779"""
780    return out
781
782def topology_to_rspec(t, filters=[]):
783    out = '<?xml version="1.0" encoding="UTF-8"?>\n' + \
784        '<rspec xmlns="http://www.protogeni.net/resources/rspec/0.1"\n' + \
785        '\txmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\n' + \
786        '\txsi:schemaLocation="http://www.protogeni.net/resources/rspec/0.1 '+ \
787        'http://www.protogeni.net/resources/rspec/0.1/request.xsd"\n' + \
788        '\ttype="request" >\n'
789
790    ifname = { }
791    ifnode = { }
792
793    for e in [e for e in t.elements if isinstance(e, Computer)]:
794        name = e.name[0]
795        virt_type = e.get_attribute("virtualization_type") or "emulab-vnode"
796        exclusive = e.get_attribute("exclusive") or "1"
797        hw = e.get_attribute("type") or "pc";
798        slots = e.get_attribute("slots") or "1";
799        startup = e.get_attribute("startup")
800        # XXX: unreliable on ProtoGENI 20100303
801        #tarfiles = " ".join([ "%s %s" % (s.install, s.location) \
802        #       for s in e.software if s.location and s.install ])
803
804        extras = ""
805        if startup: extras += '\t\tstartup_command="%s"\n' % startup
806        #if tarfiles: extras +='\t\ttarfiles="%s"\n' % tarfiles
807        out += '\t<node virtual_id="%s"\n\t\tvirtualization_type="%s"\n' % \
808                (name, virt_type)
809        out += '\t\texclusive="%s"' % exclusive
810        if extras: out += '\n%s' % extras
811        out += '>\n'
812        out += '\t\t<node_type type_name="%s" slots="%s"/>\n' % (hw, slots)
813        for i, ii in enumerate(e.interface):
814            out += '\t\t<interface virtual_id="%s"/>\n' % ii.name
815            ifnode[ii] = name
816        for f in filters:
817            out += f(s)
818        out += '\t</node>\n'
819
820    for i, s in enumerate(t.substrates):
821        if len(s.interfaces) == 0: 
822            continue
823        out += '\t<link virtual_id="%s" link_type="ethernet">\n' % s.name
824        if s.capacity and s.capacity.kind == "max":
825            bwout = True
826            out += '\t\t<bandwidth>%d</bandwidth>\n' % s.capacity.rate
827        else:
828            bwout = False
829        if s.latency and s.latency.kind == "max":
830            out += '\t\t<latency>%d</latency>\n' % s.latency.time
831        elif bwout:
832            out += '\t\t<latency>0</latency>\n'
833        for ii in s.interfaces:
834            out += ('\t\t<interface_ref virtual_node_id="%s" ' + \
835                    'virtual_interface_id="%s"/>\n') % (ifnode[ii], ii.name)
836        for f in filters:
837            out += f(s)
838        out += '\t</link>\n'
839    out += '</rspec>\n'
840    return out
841
Note: See TracBrowser for help on using the repository browser.