blob: ccabeda4c8b15637adc06020f08873f4ec1beb28 [file] [log] [blame]
Naoki Shiota2322a2f2014-05-21 19:47:40 -07001#!/usr/bin/env python
2
3"""
4start_topo.py : Mininet topology builder for multiple controller.
5
6This script reads config file and creates a Mininet topology.
7
8Usage:
9
10 $ sudo -E start_topo.py [filename]
11
12 filename: Config filename to specify topology.
13 If omitted, "topo.`hostname`.py" or "topo.py" in current
14 directory will be used.
15"""
16
17import platform
18import time
19import os.path
20import getpass
21from sys import argv
22from time import sleep
23
24from mininet.node import Controller, OVSSwitch, RemoteController
25from mininet.net import Mininet
26from mininet.cli import CLI
27from mininet.topo import Topo
28from mininet.log import setLogLevel, info, warn
29
30usage = """
31Usage: Create Mininet topology.
32 $ sudo -E %s [filename]
33 filename: config file (topo.`hostname`.py by default)
34""" % os.path.basename( argv[0] )
35
36# Mininet must be run by root user
37if ( getpass.getuser() != 'root' ):
38 print usage
39 exit( 0 )
40
41argc = len( argv )
42if ( argc > 2 ):
43 print usage
44 exit( 0 )
45
46if ( argc == 2 and ( argv[ 1 ] == "-h" or argv[ 1 ] == "--help" ) ):
47 print usage
48 exit( 0 )
49
50if ( argc == 2 ):
51 topofile = argv[1]
52else:
53 hostname = platform.node()
54 default_topo = 'topo.%s.py' % hostname
55 fallback_topo = 'topo.py'
56 topofile = default_topo if os.path.exists(default_topo) else fallback_topo
57
58if not os.path.exists( topofile ):
59 print( 'Config file %s not found' % default_topo )
60 exit( 1 )
61
62execfile( topofile )
63conf = createTopo()
64print conf
65
66class ConfigTopo( Topo ):
67 "Topology created from config."
68
69 def __init__( self, *args, **kwargs ):
70 "Create custom topo."
71
72 Topo.__init__( self, *args, **kwargs )
73
74 # Add hosts and switches
75 nmap = {}
76 for s, prop in conf[ 'switches' ].iteritems():
77 # make sure encoding is ASCII (if not, virtual eth creation fails)
78 s = s.strip().encode( 'ascii' )
79 dpid = prop[ 'dpid' ].strip().encode( 'ascii' )
80 nmap[ s ] = self.addSwitch( s, dpid=dpid )
81
82 for h, prop in conf[ 'hosts' ].iteritems():
83 h = h.strip().encode( 'ascii' )
84 nmap[ h ] =self.addHost( h )
85
86 # Add links
87 for l in conf[ 'links' ]:
88 node1 = nmap[ l[ 'node1' ] ].strip().encode( 'ascii' )
89 node2 = nmap[ l[ 'node2' ] ].strip().encode( 'ascii' )
90 self.addLink( node1, node2 )
91
92class ClusterConnectedSwitch( OVSSwitch ):
93 "OVSSwitch connected to controller cluster."
94
95 def start( self, controllers ):
96 # make sure controllers contains only a ControllerCluster
97 assert len( controllers ) == 1
98 ccluster = controllers[ 0 ]
99 assert type( ccluster ) == ControllerCluster
100
101 controller_list = ccluster.clist( self.name )
102 # TODO: manage order of controllers to control mastership
103 OVSSwitch.start( self, controllers=controller_list )
104
105class ControllerCluster( Controller ):
106 "Cluster of controllers. Relationship between controllers and switches is defined by config file"
107
108 def __init__( self, name, **params ):
109 self.sw_clist_map = {}
110 self.cmap = {}
111
112 Controller.__init__( self, name, **params )
113
114 for cname, addr in conf[ 'controllers' ].iteritems():
115 cname = cname.strip().encode( 'ascii' )
116 addr = addr.strip().encode( 'ascii' )
117 ip, port = addr.split( ':' )
118 self.cmap[ cname ] = RemoteController( cname, ip=ip, port=int( port ) )
119
120 for sw, params in conf[ 'switches' ].iteritems():
121 clist = []
122 for c in params[ 'controllers' ]:
123 assert not self.cmap[ c ] is None
124 clist.append( self.cmap[ c ] )
125 self.sw_clist_map[ sw ] = clist
126
127 def start( self ):
128 # do nothing
129 return
130
131 def stop( self ):
132 # do nothing
133 return
134
135 def checkListening( self ):
136 for c in self.cmap.values():
137 c.checkListening()
138
139 def clist( self, sw ):
140 return self.sw_clist_map[ sw ]
141
142if __name__ == '__main__':
143 setLogLevel( 'info' )
144 net = Mininet( topo=ConfigTopo(),
145 controller=ControllerCluster,
146 switch=ClusterConnectedSwitch )
147 net.start()
148 CLI( net )
149 net.stop()