Statistics
| Branch: | Tag: | Revision:

mininet / examples / controlnet.py @ 0fac568a

History | View | Annotate | Download (4.85 KB)

1
#!/usr/bin/python
2

    
3
"""
4
controlnet.py: Mininet with a custom control network
5

6
We create two Mininet() networks, a control network
7
and a data network, running four DataControllers on the
8
control network to control the data network.
9

10
Since we're using UserSwitch on the data network,
11
it should correctly fail over to a backup controller.
12

13
We also use a Mininet Facade to talk to both the
14
control and data networks from a single CLI.
15
"""
16

    
17
from functools import partial
18

    
19
from mininet.net import Mininet
20
from mininet.node import Controller, UserSwitch
21
from mininet.cli import CLI
22
from mininet.topo import Topo
23
from mininet.topolib import TreeTopo
24
from mininet.log import setLogLevel, info
25

    
26
# Some minor hacks
27

    
28
class DataController( Controller ):
29
    """Data Network Controller.
30
       patched to avoid checkListening error and to delete intfs"""
31

    
32
    def checkListening( self ):
33
        "Ignore spurious error"
34
        pass
35

    
36
    def stop( self, *args, **kwargs ):
37
        "Make sure intfs are deleted"
38
        kwargs.update( deleteIntfs=True )
39
        super( DataController, self ).stop( *args, **kwargs )
40

    
41

    
42
class MininetFacade( object ):
43
    """Mininet object facade that allows a single CLI to
44
       talk to one or more networks"""
45

    
46
    def __init__( self, net, *args, **kwargs ):
47
        """Create MininetFacade object.
48
           net: Primary Mininet object
49
           args: unnamed networks passed as arguments
50
           kwargs: named networks passed as arguments"""
51
        self.net = net
52
        self.nets = [ net ] + list( args ) + kwargs.values()
53
        self.nameToNet = kwargs
54
        self.nameToNet['net'] = net
55

    
56
    def __getattr__( self, name ):
57
        "returns attribute from Primary Mininet object"
58
        return getattr( self.net, name )
59

    
60
    def __getitem__( self, key ):
61
        "returns primary/named networks or node from any net"
62
        #search kwargs for net named key
63
        if key in self.nameToNet:
64
            return self.nameToNet[ key ]
65
        #search each net for node named key
66
        for net in self.nets:
67
            if key in net:
68
                return net[ key ]
69

    
70
    def __iter__( self ):
71
        "Iterate through all nodes in all Mininet objects"
72
        for net in self.nets:
73
            for node in net:
74
                yield node
75

    
76
    def __len__( self ):
77
        "returns aggregate number of nodes in all nets"
78
        count = 0
79
        for net in self.nets:
80
            count += len(net)
81
        return count
82

    
83
    def __contains__( self, key ):
84
        "returns True if node is a member of any net"
85
        return key in self.keys()
86

    
87
    def keys( self ):
88
        "returns a list of all node names in all networks"
89
        return list( self )
90

    
91
    def values( self ):
92
        "returns a list of all nodes in all networks"
93
        return [ self[ key ] for key in self ]
94

    
95
    def items( self ):
96
        "returns (key,value) tuple list for every node in all networks"
97
        return zip( self.keys(), self.values() )
98

    
99
# A real control network!
100

    
101
class ControlNetwork( Topo ):
102
    "Control Network Topology"
103
    def __init__( self, n, dataController=DataController, **kwargs ):
104
        """n: number of data network controller nodes
105
           dataController: class for data network controllers"""
106
        Topo.__init__( self, **kwargs )
107
        # Connect everything to a single switch
108
        cs0 = self.addSwitch( 'cs0' )
109
        # Add hosts which will serve as data network controllers
110
        for i in range( 0, n ):
111
            c = self.addHost( 'c%s' % i, cls=dataController,
112
                              inNamespace=True )
113
            self.addLink( c, cs0 )
114
        # Connect switch to root namespace so that data network
115
        # switches will be able to talk to us
116
        root = self.addHost( 'root', inNamespace=False )
117
        self.addLink( root, cs0 )
118

    
119

    
120
# Make it Happen!!
121

    
122
def run():
123
    "Create control and data networks, and invoke the CLI"
124

    
125
    info( '* Creating Control Network\n' )
126
    ctopo = ControlNetwork( n=4, dataController=DataController )
127
    cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
128
    info( '* Adding Control Network Controller\n')
129
    cnet.addController( 'cc0', controller=Controller )
130
    info( '* Starting Control Network\n')
131
    cnet.start()
132

    
133
    info( '* Creating Data Network\n' )
134
    topo = TreeTopo( depth=2, fanout=2 )
135
    # UserSwitch so we can easily test failover
136
    sw = partial( UserSwitch, opts='--inactivity-probe=1 --max-backoff=1' )
137
    net = Mininet( topo=topo, switch=sw, controller=None )
138
    info( '* Adding Controllers to Data Network\n' )
139
    for host in cnet.hosts:
140
        if isinstance(host, Controller):
141
            net.addController( host )
142
    info( '* Starting Data Network\n')
143
    net.start()
144

    
145
    mn = MininetFacade( net, cnet=cnet )
146

    
147
    CLI( mn )
148

    
149
    info( '* Stopping Data Network\n' )
150
    net.stop()
151

    
152
    info( '* Stopping Control Network\n' )
153
    cnet.stop()
154

    
155

    
156
if __name__ == '__main__':
157
    setLogLevel( 'info' )
158
    run()