TopdlLibrary: example.py

File example.py, 4.4 KB (added by faber, 7 years ago)

Full example

Line 
1#!/usr/bin/env python
2
3import sys
4from deter import topdl
5
6def annotate_degree(top):
7    '''
8    Add an attribute (node_degree) to each Computer in the topology (top) that
9    lists its degree
10    '''
11    for e in top.elements:
12        # Skip elements that are not computers
13        if not isinstance(e, topdl.Computer): continue
14        # degree is the number of interfaces
15        deg = len(e.interface)
16        # Save a string-valued attribute
17        e.set_attribute('node_degree', '%s' % deg)
18    return top
19
20def add_operating_system(top):
21    '''
22    Add an OperatingSystem class to each computer in the topology (top).  If
23    the node is a leaf (degree 1) make it Ubuntu Linux, otherwise make it
24    FreeBSD.  annotate_degree() must have been called on the topology as this
25    routine uses the node_degree attribute to make decisions.
26    '''
27
28    for e in top.elements:
29        # Skip non-Computers
30        if not isinstance(e, topdl.Computer): continue
31        a = e.get_attribute('node_degree')
32        # if there is a node_degree attribute, assign an OS
33        if a:
34            # Covnert the string attribute into an integer
35            try:
36                deg = int(a)
37            except ValueError, e:
38                sys.exit('%s has a non-integer degree %s!?' % (e.name, a))
39            # Assign the os - includes a distribution for Linux
40            if deg == 1:
41                e.os.append(topdl.OperatingSystem(name='Linux', 
42                    distribution='Ubuntu'))
43            else:
44                e.os.append(topdl.OperatingSystem(name='FreeBSD'))
45    return top
46
47def add_links(top):
48    '''
49    For each router - Computer with FreeBSD assigned as an OS - select one of
50    its Linux children and make a connection to one of the other router's
51    children.
52    '''
53
54    def has_os(e, os_name):
55        '''
56        Return true if any of e's os classes has the given os_name
57        '''
58        if e.os is None: return False
59        else: return any([ o.name == os_name for o in e.os ])
60
61    # At the end of this loop, leaves contains a list of leaves for each router
62    # in the topology.
63    leaves = [ ]
64    for e in top.elements:
65        if not isinstance(e, topdl.Computer): continue
66        if not has_os(e, 'FreeBSD'): continue
67        # This is a Computer running FreeBsd
68        my_leaves = []
69        # walk the interfaces
70        for inf in e.interface:
71            # Walk the interface's substrates
72            for s in inf.subs:
73                # Walk the substrate's interfaces looking for the other
74                # elements - not this router.
75                for sinf in s.interfaces:
76                    ee = sinf.element
77                    # all the Linux computers get attached to the leaves dict
78                    if isinstance(ee, topdl.Computer) and ee != e:
79                        if has_os(ee, 'Linux'):
80                            my_leaves.append(ee)
81        # One router has no leaves.  Ignore it.
82        if len(my_leaves) > 0:
83            leaves.append(my_leaves)
84
85
86    # This loop takes the first computer in one entry in leaves and connects it
87    # to the last computer in the next entry in leaves (wrapping around at the
88    # top).
89    for i in range(0, len(leaves)):
90        link_name = 'new-link%d' % i
91        f = leaves[i][0]
92        t = leaves[(i+1) % len(leaves)][-1]
93        f.interface.append(topdl.Interface(substrate=[link_name]))
94        t.interface.append(topdl.Interface(substrate=[link_name]))
95        top.substrates.append(topdl.Substrate(name=link_name))
96
97    # Now incorporate the new links
98    top.incorporate_elements()
99    return top
100
101def output_ns(top, filename):
102    '''
103    Output ns2 with the OperatingSystem specifications converted to local OSIDs
104    when known.
105    '''
106    def os_filter(e):
107        '''
108        Convert OS id to local equivalents:
109            FreeBSD -> FBSD8-STD
110            Lunix/Ubuntu -> Ubuntu-64-STD
111        '''
112        # Only work on Computers
113        if not isinstance(e, topdl.Computer): return ''
114        # Only handle exactly 1 specified OS
115        if len(e.os) != 1 : return ''
116        # String translation
117        if e.os[0].name == 'FreeBSD': 
118            return 'tb-set-node-os ${%s} FBSD8-STD\n' % \
119                    topdl.to_tcl_name(e.name)
120        elif e.os[0].name == 'Linux' and e.os[0].distribution == 'Ubuntu':
121            return 'tb-set-node-os ${%s} Ubuntu1204-64-STD\n' % \
122                    topdl.to_tcl_name(e.name)
123        else:
124            return ''
125
126    # Main line.  Open the file and write the otcl to it.
127    try:
128        f = open(filename, 'w')
129        # Include the os_filter
130        f.write(topdl.topology_to_ns2(top, 
131            filters=[os_filter], routing='Static'))
132        f.close()
133    except EnvironmentError, e:
134        sys.exit('Cannot write %s: %s' % (e.filename, e.strerror))
135
136
137# Parse get the file to parse and output file
138if len(sys.argv) > 2:
139    infile, outfile = (sys.argv[1], sys.argv[2])
140else:
141    sys.exit('Usage: %s infile outfile' % sys.argv[0])
142
143top = topdl.topology_from_xml(filename=infile, top='experiment')
144top = annotate_degree(top)
145top = add_operating_system(top)
146top = add_links(top)
147output_ns(top, outfile)