Merge branch 'master' into fw
diff --git a/perf-scripts/flow-sync-perf.py b/perf-scripts/flow-sync-perf.py
index f0af050..b782333 100755
--- a/perf-scripts/flow-sync-perf.py
+++ b/perf-scripts/flow-sync-perf.py
@@ -203,7 +203,7 @@
setLogLevel( 'output' )
resultDir = strftime( '%Y%m%d-%H%M%S' )
os.mkdir( resultDir )
- tests = sys.argv[1:]
+ tests = map(int, sys.argv[1:])
if not tests:
tests = [1, 10, 100, 1000, 10000]
runPerf( resultDir, tests )
diff --git a/start-onos.sh b/start-onos.sh
index 29a108c..a9d4d64 100755
--- a/start-onos.sh
+++ b/start-onos.sh
@@ -1,21 +1,21 @@
#!/bin/bash
# Set paths
-if [ -z "${ONOS_HOME}" ]; then
- ONOS_HOME=`dirname $0`
-fi
+ONOS_HOME="${ONOS_HOME:-`dirname $0`}"
## Because the script change dir to $ONOS_HOME, we can set ONOS_LOGBACK and LOGDIR relative to $ONOS_HOME
-#ONOS_LOGBACK="${ONOS_HOME}/logback.`hostname`.xml"
-#LOGDIR=${ONOS_HOME}/onos-logs
-ONOS_LOGBACK="./logback.`hostname`.xml"
-LOGDIR=./onos-logs
+ONOS_LOGBACK=${ONOS_LOGBACK:-${ONOS_HOME}/logback.`hostname`.xml}
+LOGDIR=${ONOS_LOGDIR:-${ONOS_HOME}/onos-logs}
+
ONOS_LOG="${LOGDIR}/onos.`hostname`.log"
PCAP_LOG="${LOGDIR}/onos.`hostname`.pcap"
LOGS="$ONOS_LOG $PCAP_LOG"
+ONOS_PROPS=${ONOS_PROPS:-${ONOS_HOME}/conf/onos.properties}
+JMX_PORT=${JMX_PORT:-7189}
+
# Set JVM options
-JVM_OPTS=""
+JVM_OPTS="${JVM_OPTS:-}"
## If you want JaCoCo Code Coverage reports... uncomment line below
#JVM_OPTS="$JVM_OPTS -javaagent:${ONOS_HOME}/lib/jacocoagent.jar=dumponexit=true,output=file,destfile=${LOGDIR}/jacoco.exec"
JVM_OPTS="$JVM_OPTS -server -d64"
@@ -31,7 +31,7 @@
-XX:+UseThreadPriorities \
-XX:ThreadPriorityPolicy=42 \
-XX:+UseCompressedOops \
- -Dcom.sun.management.jmxremote.port=7189 \
+ -Dcom.sun.management.jmxremote.port=$JMX_PORT \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false"
JVM_OPTS="$JVM_OPTS -Dhazelcast.logging.type=slf4j"
@@ -39,9 +39,7 @@
# Set ONOS core main class
MAIN_CLASS="net.onrc.onos.ofcontroller.core.Main"
-if [ -z "${MVN}" ]; then
- MVN="mvn -o"
-fi
+MVN=${MVN:-mvn -o}
#<logger name="net.floodlightcontroller.linkdiscovery.internal" level="TRACE"/>
#<appender-ref ref="STDOUT" />
@@ -101,15 +99,15 @@
# Run ONOS
echo "Starting ONOS controller ..."
- echo
+ echo
- # XXX : MVN has to run at the project top dir
+ # XXX : MVN has to run at the project top dir
echo $ONOS_HOME
cd ${ONOS_HOME}
- pwd
- echo "${MVN} exec:exec -Dexec.executable=\"java\" -Dexec.args=\"${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ./conf/onos.properties\""
+ pwd
+ echo "${MVN} exec:exec -Dexec.executable=\"java\" -Dexec.args=\"${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ${ONOS_PROPS}\""
- ${MVN} exec:exec -Dexec.executable="java" -Dexec.args="${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ./conf/onos.properties" > ${LOGDIR}/onos.`hostname`.stdout 2>${LOGDIR}/onos.`hostname`.stderr &
+ ${MVN} exec:exec -Dexec.executable="java" -Dexec.args="${JVM_OPTS} -Dlogback.configurationFile=${ONOS_LOGBACK} -cp %classpath ${MAIN_CLASS} -cf ${ONOS_PROPS}" > ${LOGDIR}/onos.`hostname`.stdout 2>${LOGDIR}/onos.`hostname`.stderr &
echo "Waiting for ONOS to start..."
COUNT=0
@@ -161,13 +159,17 @@
start)
stop
check_db
- start
+ start
+ ;;
+ startnokill)
+ check_db
+ start
;;
startifdown)
n=`jps -l |grep "${MAIN_CLASS}" | wc -l`
if [ $n == 0 ]; then
start
- else
+ else
echo "$n instance of onos running"
fi
;;
diff --git a/vm-utils/onos.py b/vm-utils/onos.py
new file mode 100755
index 0000000..c6b96dd
--- /dev/null
+++ b/vm-utils/onos.py
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+
+"""
+onos.py: A simple ONOS Controller() subclass for Mininet
+
+We implement the following classes:
+
+ONOSController: a custom Controller() subclass to start ONOS
+OVSSwitchONOS: a custom OVSSwitch() switch that connects to multiple controllers.
+
+We use single Zookeeper and Cassandra instances for now.
+
+As a custom file, exports:
+
+--controller onos
+--switch ovso
+
+Usage:
+
+$ sudo ./onos.py
+
+This will start up a simple 2-host, 2 ONOS network
+
+$ sudo mn --custom onos.py --controller onos,2 --switch ovso
+"""
+
+from mininet.node import Controller, OVSSwitch
+from mininet.net import Mininet
+from mininet.cli import CLI
+from mininet.topo import SingleSwitchTopo
+from mininet.log import setLogLevel, info
+from mininet.util import quietRun
+
+from shutil import copyfile
+from os import environ
+from functools import partial
+
+
+class ONOS( Controller ):
+ "Custom controller class for ONOS"
+
+ # Directories and configuration templates
+ home = environ[ 'HOME' ]
+ onosDir = home + "/ONOS"
+ zookeeperDir = home + "/zookeeper-3.4.5"
+ dirBase = '/tmp'
+ logDir = dirBase + '/onos-%s.logs'
+ cassDir = dirBase + '/onos-%s.cassandra'
+ configFile = dirBase + '/onos-%s.properties'
+ logbackFile = dirBase + '/onos-%s.logback'
+ jmxbase = 7189
+ restbase = 8080
+ ofbase = 6633
+
+ # Per-instance property template
+ fc = 'net.floodlightcontroller.'
+ proctag = 'mn-onos-id'
+ jvmopts = (
+ # We match on this to shut down our instances
+ ( proctag, 0 ),
+ ( fc + 'restserver.RestApiServer.port', restbase ),
+ ( fc + 'core.FloodlightProvider.openflowport', ofbase ),
+ ( fc + 'core.FloodlightProvider.controllerid', 0 ) )
+
+
+ # For maven debugging
+ # mvn = 'mvn -o -e -X'
+
+ def __init__( self, name, n=1, drop=True, **params):
+ """n: number of ONOS instances to run (1)
+ drop: drop root privileges (True)"""
+ self.check()
+ self.drop = drop
+ self.count = n
+ self.ids = range( 0, self.count )
+ Controller.__init__( self, name, **params )
+ # We don't need to run as root, and it can interfere
+ # with starting Zookeeper manually
+ if self.drop:
+ self.user = quietRun( 'who am i' ).split()[ 0 ]
+ self.sendCmd( 'su', self.user )
+ self.waiting = False
+ # Need to run commands from ONOS dir
+ self.cmd( 'cd', self.onosDir )
+ self.cmd( 'export PATH=$PATH:%s' % self.onosDir )
+ if hasattr( self, 'mvn' ):
+ self.cmd( 'export MVN="%s"' % self.mvn )
+
+ def check( self ):
+ "Check for prerequisites"
+ if not quietRun( 'which java' ):
+ raise Exception( 'java not found -'
+ ' make sure it is installed and in $PATH' )
+ if not quietRun( 'which mvn' ):
+ raise Exception( 'Maven (mvn) not found -'
+ ' make sure it is installed and in $PATH' )
+
+ def startCassandra( self ):
+ "Start Cassandra"
+ self.cmd( 'start-cassandra.sh start' )
+ status = self.cmd( 'start-cassandra.sh status' )
+ if 'Error' in status:
+ raise Exception( 'Cassandra startup failed: ' + status )
+
+ def stopCassandra( self ):
+ "Stop Cassandra"
+ self.cmd( 'start-cassandra.sh stop' )
+
+ def startZookeeper( self, initcfg=True ):
+ "Start Zookeeper"
+ # Reinitialize configuration file
+ if initcfg:
+ cfg = self.zookeeperDir + '/conf/zoo.cfg'
+ template = self.zookeeperDir + '/conf/zoo_sample.cfg'
+ copyfile( template, cfg )
+ self.cmd( 'start-zk.sh restart' )
+ status = self.cmd( 'start-zk.sh status' )
+ if 'Error' in status:
+ raise Exception( 'Zookeeper startup failed: ' + status )
+
+ def stopZookeeper( self ):
+ "Stop Zookeeper"
+ self.cmd( 'start-zk.sh stop' )
+
+ def setVars( self, id ):
+ "Set and return environment vars"
+ # ONOS directories and files
+ logdir = self.logDir % id
+ cassdir = self.cassDir % id
+ logback = self.logbackFile % id
+ jmxport = self.jmxbase + id
+ self.cmd( 'mkdir -p', logdir, cassdir )
+ self.cmd( 'export ONOS_LOGDIR="%s"' % logdir )
+ self.cmd( 'export ZOO_LOG_DIR="%s"' % logdir )
+ self.cmd( 'export CASS_DIR="%s"' % cassdir )
+ self.cmd( 'export ONOS_LOGBACK="%s"' % logback )
+ self.cmd( 'export JMX_PORT=%s' % jmxport )
+ jvmopts = ('-agentlib:jdwp=transport=dt_socket,address=%s,server=y,suspend=n '
+ % ( 8000 + id ) )
+ jvmopts += ' '.join( '-D%s=%s '% ( opt, val + id )
+ for opt, val in self.jvmopts )
+ self.cmd( 'export JVM_OPTS="%s"' % jvmopts )
+
+ def startONOS( self, id ):
+ """Start ONOS
+ id: identifier for new instance"""
+ # self.stopONOS( id )
+ self.setVars( id )
+ self.cmdPrint( 'start-onos.sh startnokill' )
+
+ def stopONOS( self, id ):
+ """Shut down ONOS
+ id: identifier for instance"""
+ pid = self.cmd( "jps -v | grep %s=%s | awk '{print $1}'" %
+ ( self.proctag, id ) ).strip()
+ if pid:
+ self.cmdPrint( 'kill', pid )
+
+ def start( self, *args ):
+ "Start ONOS instances"
+ info( '* Starting Cassandra\n' )
+ self.startCassandra()
+ info( '* Starting Zookeeper\n' )
+ self.startZookeeper()
+ for id in self.ids:
+ info( '* Starting ONOS %s\n' % id )
+ self.startONOS( id )
+
+ def stop( self, *args ):
+ "Stop ONOS instances"
+ for id in self.ids:
+ info( '* Stopping ONOS %s\n' % id )
+ self.stopONOS( id )
+ info( '* Stopping zookeeper\n' )
+ self.stopZookeeper()
+ info( '* Stopping Cassandra\n' )
+ self.stopCassandra()
+
+ def clist( self ):
+ "Return list of controller specifiers (proto:ip:port)"
+ return [ 'tcp:127.0.0.1:%s' % ( self.ofbase + id )
+ for id in range( 0, self.count ) ]
+
+
+class OVSSwitchONOS( OVSSwitch ):
+ "OVS switch which connects to multiple controllers"
+ def start( self, controllers ):
+ OVSSwitch.start( self, controllers )
+ assert len( controllers ) == 1
+ c0 = controllers[ 0 ]
+ assert type( c0 ) == ONOS
+ clist = ','.join( c0.clist() )
+ self.cmd( 'ovs-vsctl set-controller', self, clist)
+ # Reconnect quickly to controllers (1s vs. 15s max_backoff)
+ for uuid in self.controllerUUIDs():
+ if uuid.count( '-' ) != 4:
+ # Doesn't look like a UUID
+ continue
+ uuid = uuid.strip()
+ self.cmd( 'ovs-vsctl set Controller', uuid,
+ 'max_backoff=1000' )
+
+
+controllers = { 'onos': ONOS }
+switches = { 'ovso': OVSSwitchONOS }
+
+
+if __name__ == '__main__':
+ "Simple test of ONOSController"
+ setLogLevel( 'info' )
+ net = Mininet( topo=SingleSwitchTopo( 2 ),
+ controller=partial( ONOS, n=2 ),
+ switch=OVSSwitchONOS )
+ net.start()
+ CLI( net )
+ net.stop()