mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-17 10:21:52 +02:00
226 lines
8.0 KiB
Python
Executable File
226 lines
8.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# TODO add onos-app-fwd to features
|
|
# TODO check if service is running... i think this might already be done by mn
|
|
|
|
from mininet.node import Controller, OVSSwitch, CPULimitedHost, RemoteController
|
|
from mininet.net import Mininet
|
|
from mininet.cli import CLI
|
|
from mininet.topo import LinearTopo, Topo
|
|
from mininet.log import setLogLevel, info, warn
|
|
from mininet.util import quietRun, numCores
|
|
|
|
from shutil import copyfile
|
|
from os import environ, path
|
|
from functools import partial
|
|
import time
|
|
from sys import argv
|
|
from time import sleep
|
|
from sets import Set
|
|
|
|
class ONOS( Controller ):
|
|
"TODO"
|
|
|
|
onosDir = '/opt/onos/'
|
|
|
|
def __init__( self, name, onosDir=onosDir,
|
|
reactive=True, features=[ 'onos-app-tvue' ],
|
|
**kwargs ):
|
|
'''TODO'''
|
|
|
|
Controller.__init__( self, name, **kwargs )
|
|
# the following have been done for us:
|
|
#self.ip = ip ('127.0.0.1')
|
|
#self.port = port (6653)
|
|
#self.protocol = protocol ('tcp')
|
|
#self.checkListening()
|
|
|
|
self.onosDir = onosDir
|
|
self.karafDir = onosDir + 'apache-karaf-3.0.3/'
|
|
self.instanceDir = self.karafDir
|
|
|
|
# add default modules
|
|
# TODO: consider an ordered set
|
|
self.features = Set([ 'webconsole',
|
|
'onos-rest',
|
|
'onos-api',
|
|
'onos-cli',
|
|
'onos-openflow' ])
|
|
self.features.update( features )
|
|
# add reactive forwarding modules
|
|
if reactive:
|
|
self.features.update( ['onos-app-fwd',
|
|
'onos-app-proxyarp',
|
|
'onos-app-mobility' ] )
|
|
# add the distributed core if we are in a namespace with no trivial core
|
|
if self.inNamespace and 'onos-core-trivial' not in self.features:
|
|
self.features.add( 'onos-core' )
|
|
# if there is no core, add the trivial one
|
|
if 'onos-core' not in self.features:
|
|
self.features.add( 'onos-core-trivial' )
|
|
print self.features
|
|
|
|
def start( self ):
|
|
if self.inNamespace:
|
|
instanceOpts = ( '-furl mvn:org.onosproject/onos-features/1.5.0-SNAPSHOT/xml/features '
|
|
'-s 8101' )
|
|
if self.ip is not None:
|
|
instanceOpts += (' -a %s' % self.IP() )
|
|
self.userCmd( self.karafDir + 'bin/instance create %s %s' % ( instanceOpts, self.name ) )
|
|
self.instanceDir = self.karafDir + 'instances/%s/' % self.name
|
|
else:
|
|
# we are running in the root namespace, so let's use the root instance
|
|
# clean up the data directory
|
|
#self.userCmd( 'rm -rf '+ self.karafDir + 'data/' )
|
|
pass
|
|
|
|
self.userCmd( 'rm -rf '+ self.instanceDir + 'data/' )
|
|
|
|
# Update etc/org.apache.karaf.features.cfg
|
|
self.updateFeatures()
|
|
|
|
# TODO 2. Update etc/hazelcast.xml : interface lines
|
|
#cp etc/hazelcast.xml instances/c1/etc/
|
|
self.updateHazelcast()
|
|
|
|
# TODO 3. Update etc/system.properties : onos.ip
|
|
# TODO 4. Update config/cluster.json : with all nodes
|
|
|
|
# start onos
|
|
self.userCmd( '%sbin/instance start -d %s' % ( self.karafDir, self.name ) )
|
|
#TODO we should wait for startup...
|
|
|
|
def stop( self ):
|
|
self.userCmd( self.instanceDir + 'bin/stop' )
|
|
#if self.inNamespace:
|
|
# self.userCmd( self.karafDir + 'bin/instance destroy %s' % self.name )
|
|
self.terminate()
|
|
|
|
def updateHazelcast( self ):
|
|
hz = '192.168.123.*'
|
|
if self.ip is not None:
|
|
hz = '.'.join(self.ip.split('.')[:-1]) + '.*'
|
|
|
|
readfile = self.karafDir + 'etc/hazelcast.xml'
|
|
writefile = self.instanceDir + 'etc/hazelcast.xml'
|
|
with open( readfile, 'r' ) as r:
|
|
with open( writefile, 'w' ) as w:
|
|
for line in r.readlines():
|
|
if '<interface>' in line:
|
|
line = '<interface>' + hz + '</interface>\n'
|
|
w.write( line )
|
|
|
|
def updateFeatures( self ):
|
|
filename = self.instanceDir + 'etc/org.apache.karaf.features.cfg'
|
|
with open( filename, 'r+' ) as f:
|
|
lines = f.readlines()
|
|
f.seek(0)
|
|
f.truncate()
|
|
for line in lines:
|
|
#print '?', line,
|
|
if 'featuresBoot=' in line:
|
|
# parse the features from the line
|
|
features = line.rstrip().split('=')[1].split(',')
|
|
# add the features to our features set
|
|
self.features.update( features )
|
|
# generate the new features line
|
|
line = 'featuresBoot=' + ','.join( self.features ) + '\n'
|
|
#print '!', line,
|
|
f.write( line )
|
|
|
|
|
|
@classmethod
|
|
def isAvailable( self ):
|
|
return quietRun( 'ls %s' % self.onosDir )
|
|
|
|
def userCmd( self, cmd ):
|
|
# switch to the non-root user because karaf gets upset otherwise
|
|
# because the .m2repo is not stored with root
|
|
cmd = 'sudo -u %s %s' % ( self.findUser(), cmd )
|
|
return self.cmd( cmd )
|
|
|
|
@staticmethod
|
|
def findUser():
|
|
"Try to return logged-in (usually non-root) user"
|
|
try:
|
|
# If we're running sudo
|
|
return os.environ[ 'SUDO_USER' ]
|
|
except:
|
|
try:
|
|
# Logged-in user (if we have a tty)
|
|
return quietRun( 'who am i' ).split()[ 0 ]
|
|
except:
|
|
# Give up and return effective user
|
|
return quietRun( 'whoami' )
|
|
|
|
|
|
class ControlNetwork( Topo ):
|
|
"Control Network Topology"
|
|
def __init__( self, n, dataController=ONOS, **kwargs ):
|
|
"""n: number of data network controller nodes
|
|
dataController: class for data network controllers"""
|
|
Topo.__init__( self, **kwargs )
|
|
# Connect everything to a single switch
|
|
cs0 = self.addSwitch( 'cs0' )
|
|
# Add hosts which will serve as data network controllers
|
|
for i in range( 1, n+1 ):
|
|
c = self.addHost( 'c%s' % i, cls=dataController,
|
|
inNamespace=True )
|
|
self.addLink( c, cs0 )
|
|
# Connect switch to root namespace so that data network
|
|
# switches will be able to talk to us
|
|
root = self.addHost( 'root', inNamespace=False )
|
|
self.addLink( root, cs0 )
|
|
|
|
class ONOSCluster( Controller ):
|
|
# TODO
|
|
n = 3
|
|
|
|
def start( self ):
|
|
ctopo = ControlNetwork( n=self.n, dataController=ONOS )
|
|
self.cnet = Mininet( topo=ctopo, ipBase='192.168.123.0/24', controller=None )
|
|
self.cnet.addController( 'cc0', controller=Controller )
|
|
self.cnet.start()
|
|
|
|
self.ctrls = []
|
|
for host in self.cnet.hosts:
|
|
if isinstance( host, Controller ):
|
|
self.ctrls.append( host )
|
|
host.start()
|
|
|
|
def stop( self ):
|
|
for host in self.cnet.hosts:
|
|
if isinstance( host, Controller ):
|
|
host.stop()
|
|
self.cnet.stop()
|
|
|
|
def clist( self ):
|
|
"Return list of Controller proxies for this ONOS cluster"
|
|
print 'controllers:', self.ctrls
|
|
return self.ctrls
|
|
|
|
class OVSSwitchONOS( OVSSwitch ):
|
|
"OVS switch which connects to multiple controllers"
|
|
def start( self, controllers ):
|
|
assert len( controllers ) == 1
|
|
c0 = controllers[ 0 ]
|
|
assert type( c0 ) == ONOSCluster
|
|
controllers = c0.clist()
|
|
OVSSwitch.start( self, controllers )
|
|
|
|
controllers = { 'onos': ONOS }
|
|
switches = { 'ovso': OVSSwitchONOS }
|
|
|
|
if __name__ == '__main__':
|
|
# Simple test for ONOS() controller class
|
|
setLogLevel( 'info' ) #TODO info
|
|
size = 2 if len( argv ) != 2 else int( argv[ 1 ] )
|
|
net = Mininet( topo=LinearTopo( size ),
|
|
#controller=ONOS,
|
|
controller=partial( ONOSCluster, n=3 ), #TODO
|
|
switch=OVSSwitchONOS )
|
|
net.start()
|
|
#waitConnected( net.switches )
|
|
CLI( net )
|
|
net.stop()
|