source: fedd/federation/topdl.py @ da2208a

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

Coerce all attributes that we think are strings into being strings in the
constructors. We've seen cases, especically when constructing topologies from
ZSI calls (SOAP) where things that look like strings but are unpicklable show
up.

Bottom line - if we expect 'em to be strings we should force 'em to be to the
extent we can.

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