blob: ba09f678ca6155c9157fb10bb162c0c91e0cdfdb [file] [log] [blame]
Brian O'Connor195191b2014-10-22 01:09:36 -07001#!/usr/bin/env python
2
3# TODO add onos-app-fwd to features
4# TODO check if service is running... i think this might already be done by mn
5
6from mininet.node import Controller, OVSSwitch, CPULimitedHost, RemoteController
7from mininet.net import Mininet
8from mininet.cli import CLI
9from mininet.topo import LinearTopo, Topo
10from mininet.log import setLogLevel, info, warn
11from mininet.util import quietRun, numCores
12
13from shutil import copyfile
14from os import environ, path
15from functools import partial
16import time
17from sys import argv
18from time import sleep
19
20class ONOS( Controller ):
21 #def __init__( self, name, command='/opt/onos/bin/onos-service', **kwargs ):
22 # Controller.__init__( self, name, command=command, inNamespace=True, **kwargs )
23 #def __init__( self, name, inNamespace=False, command='controller',
24 # cargs='-v ptcp:%d', cdir=None, ip="127.0.0.1",
25 # port=6633, protocol='tcp', **params ):
26 #self.command = command
27 #self.cargs = cargs
28 #self.cdir = cdir
29 #self.ip = ip
30 #self.port = port
31 #self.protocol = protocol
32 #Node.__init__( self, name, inNamespace=inNamespace,
33 # ip=ip, **params )
34 #self.checkListening()
35
36 ONOS_DIR = '/opt/onos/'
37 KARAF_DIR = ONOS_DIR + 'apache-karaf-3.0.1/'
38 reactive = True
39
40 def start( self ):
41 # switch to the non-root user because karaf gets upset otherwise
42 # TODO we should look into why....
43 self.sendCmd( 'sudo su - %s' % self.findUser() )
44 self.waiting = False
45
46 if self.inNamespace:
47 self.cmd( self.KARAF_DIR + 'bin/instance create %s' % self.name )
48 src = self.KARAF_DIR + 'etc/org.apache.karaf.features.cfg'
49 dst = self.KARAF_DIR + 'instances/%s/etc/org.apache.karaf.features.cfg' % self.name
50 self.cmd( 'cp %s %s' % (src, dst) )
51 self.updateProperties( dst )
52 self.cmd( self.KARAF_DIR + 'bin/instance start %s' % self.name )
53 else:
54 # we are running in the root namespace, so let's use the root instance
55 self.cmd( 'rm -rf '+ self.KARAF_DIR + 'data/' )
56 filename = self.KARAF_DIR + 'etc/org.apache.karaf.features.cfg'
57 self.updateProperties( filename )
58 self.cmd( self.KARAF_DIR + 'bin/start' )
59
60 #TODO we should wait for startup...
61
62 def stop( self ):
63 if self.inNamespace:
64 self.cmd( '/opt/onos/apache-karaf-3.0.1/bin/instance stop %s' % self.name )
65 self.cmd( '/opt/onos/apache-karaf-3.0.1/bin/instance destroy %s' % self.name )
66 else:
67 self.cmd( self.ONOS_DIR + 'apache-karaf-3.0.1/bin/stop' )
68 self.terminate()
69
70 def updateProperties( self, filename ):
71 with open( filename, 'r+' ) as f:
72 lines = f.readlines()
73 f.seek(0)
74 f.truncate()
75 for line in lines:
76 #print '?', line,
77 if 'featuresBoot=' in line:
78 line = line.rstrip()
79 #print ord(line[-1]), ord(line[-2]), ord(line[-3])
80 if self.reactive:
81 line += ',onos-app-fwd'
82 line += '\n'
83 #print '!', line,
84 f.write( line )
85
86 @classmethod
87 def isAvailable( self ):
88 return quietRun( 'ls /opt/onos' )
89
90 @staticmethod
91 def findUser():
92 "Try to return logged-in (usually non-root) user"
93 try:
94 # If we're running sudo
95 return os.environ[ 'SUDO_USER' ]
96 except:
97 try:
98 # Logged-in user (if we have a tty)
99 return quietRun( 'who am i' ).split()[ 0 ]
100 except:
101 # Give up and return effective user
102 return quietRun( 'whoami' )
103
104
105class ControlNetwork( Topo ):
106 "Control Network Topology"
107 def __init__( self, n, dataController=ONOS, **kwargs ):
108 """n: number of data network controller nodes
109 dataController: class for data network controllers"""
110 Topo.__init__( self, **kwargs )
111 # Connect everything to a single switch
112 cs0 = self.addSwitch( 'cs0' )
113 # Add hosts which will serve as data network controllers
114 for i in range( 0, n ):
115 c = self.addHost( 'c%s' % i, cls=dataController,
116 inNamespace=True )
117 self.addLink( c, cs0 )
118 # Connect switch to root namespace so that data network
119 # switches will be able to talk to us
120 root = self.addHost( 'root', inNamespace=False )
121 self.addLink( root, cs0 )
122
123class ONOSCluster( Controller ):
124 # TODO
125 n = 4
126
127 def start( self ):
128 ctopo = ControlNetwork( n=self.n, dataController=ONOS )
129 self.cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
130 self.cnet.addController( 'cc0', controller=Controller )
131 self.cnet.start()
132
133 self.ctrls = []
134 for host in self.cnet.hosts:
135 if isinstance( host, Controller ):
136 self.ctrls.append( host )
137 host.start()
138
139 def stop( self ):
140 self.cnet.stop()
141
142 def clist( self ):
143 "Return list of Controller proxies for this ONOS cluster"
144 print 'controllers:', self.ctrls
145 return self.ctrls
146
147class OVSSwitchONOS( OVSSwitch ):
148 "OVS switch which connects to multiple controllers"
149 def start( self, controllers ):
150 assert len( controllers ) == 1
151 c0 = controllers[ 0 ]
152 assert type( c0 ) == ONOSCluster
153 controllers = c0.clist()
154 OVSSwitch.start( self, controllers )
155
156controllers = { 'onos': ONOS }
157switches = { 'ovso': OVSSwitchONOS }
158
159if __name__ == '__main__':
160 # Simple test for ONOS() controller class
161 setLogLevel( 'info' )
162 size = 2 if len( argv ) != 2 else int( argv[ 1 ] )
163 net = Mininet( topo=LinearTopo( size ),
164 controller=partial( ONOSCluster, n=4 ),
165 switch=OVSSwitchONOS )
166 net.start()
167 #waitConnected( net.switches )
168 CLI( net )
169 net.stop()