source: fedd/federation/topdl.py @ 4d4dde4

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

Imbedded import? Not a good idea; dunno what I was thinking

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