Brian O'Connor

adding onos.py, a work in progress

Change-Id: Idfc2087fd8be2ffa24e7e93c2744fa8b1d46811b
1 +#!/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 +
6 +from mininet.node import Controller, OVSSwitch, CPULimitedHost, RemoteController
7 +from mininet.net import Mininet
8 +from mininet.cli import CLI
9 +from mininet.topo import LinearTopo, Topo
10 +from mininet.log import setLogLevel, info, warn
11 +from mininet.util import quietRun, numCores
12 +
13 +from shutil import copyfile
14 +from os import environ, path
15 +from functools import partial
16 +import time
17 +from sys import argv
18 +from time import sleep
19 +
20 +class 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 +
105 +class 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 +
123 +class 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 +
147 +class 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 +
156 +controllers = { 'onos': ONOS }
157 +switches = { 'ovso': OVSSwitchONOS }
158 +
159 +if __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()