source: fedd/federation/topdl.py @ 5bf359d

axis_examplecompt_changesinfo-opsversion-3.01version-3.02
Last change on this file since 5bf359d was 21b5434, checked in by Ted Faber <faber@…>, 15 years ago

The string coercion was turning perfectly valid None types into 'None" strings. Modified the string coercion to respect None.

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