updating onos.py

Change-Id: I6ec6bf1205d0d3175495a7ecef4c2a4156d2e25a
diff --git a/tools/test/topos/onos.py b/tools/test/topos/onos.py
index ba09f67..9566d00 100755
--- a/tools/test/topos/onos.py
+++ b/tools/test/topos/onos.py
@@ -16,58 +16,95 @@
 import time
 from sys import argv
 from time import sleep
+from sets import Set
 
 class ONOS( Controller ):
-    #def __init__( self, name, command='/opt/onos/bin/onos-service', **kwargs ):
-    #    Controller.__init__( self, name, command=command, inNamespace=True,  **kwargs )
-    #def __init__( self, name, inNamespace=False, command='controller',
-    #          cargs='-v ptcp:%d', cdir=None, ip="127.0.0.1",
-    #          port=6633, protocol='tcp', **params ):
-    #self.command = command
-    #self.cargs = cargs
-    #self.cdir = cdir
-    #self.ip = ip
-    #self.port = port
-    #self.protocol = protocol
-    #Node.__init__( self, name, inNamespace=inNamespace,
-    #               ip=ip, **params  )
-    #self.checkListening()
-    
-    ONOS_DIR = '/opt/onos/'
-    KARAF_DIR = ONOS_DIR + 'apache-karaf-3.0.1/'
-    reactive = True
+    "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 (6633)
+        #self.protocol = protocol ('tcp')
+        #self.checkListening()
+
+        self.onosDir = onosDir
+        self.karafDir = onosDir + 'apache-karaf-3.0.1/'
+        self.instanceDir = self.karafDir
+
+        # add default modules
+        # TODO: consider an ordered set
+        self.features = Set([ 'webconsole',
+                              '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 ):
-        # switch to the non-root user because karaf gets upset otherwise
-        # TODO we should look into why.... 
-        self.sendCmd( 'sudo su - %s' % self.findUser() )
-        self.waiting = False
-
         if self.inNamespace:
-            self.cmd( self.KARAF_DIR + 'bin/instance create %s' % self.name )
-            src  = self.KARAF_DIR + 'etc/org.apache.karaf.features.cfg'
-            dst = self.KARAF_DIR + 'instances/%s/etc/org.apache.karaf.features.cfg' % self.name
-            self.cmd( 'cp %s %s' % (src, dst) )
-            self.updateProperties( dst )
-            self.cmd( self.KARAF_DIR + 'bin/instance start %s' % self.name )
+            instanceOpts = ( '-furl mvn:org.onlab.onos/onos-features/1.0.0-SNAPSHOT/xml/features '
+                             '-s 8101' )
+            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
-            self.cmd( 'rm -rf '+ self.KARAF_DIR + 'data/' )
-            filename = self.KARAF_DIR + 'etc/org.apache.karaf.features.cfg'
-            self.updateProperties( filename )
-            self.cmd( self.KARAF_DIR + 'bin/start' )
+            # 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( self.instanceDir + 'bin/start' )
         #TODO we should wait for startup...
 
     def stop( self ):
-        if self.inNamespace:
-            self.cmd( '/opt/onos/apache-karaf-3.0.1/bin/instance stop %s' % self.name )
-            self.cmd( '/opt/onos/apache-karaf-3.0.1/bin/instance destroy %s' % self.name )
-        else:
-            self.cmd( self.ONOS_DIR + 'apache-karaf-3.0.1/bin/stop' )
+        self.userCmd( self.instanceDir + 'bin/stop' )
+        #if self.inNamespace:
+        #    self.userCmd( self.karafDir + 'bin/instance destroy %s' % self.name )
         self.terminate()
 
-    def updateProperties( self, filename ):
+    def updateHazelcast( self ):
+        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>' + '192.168.123.*' + '</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)
@@ -75,17 +112,25 @@
             for line in lines:
                 #print '?', line,
                 if 'featuresBoot=' in line:
-                    line = line.rstrip()
-                    #print ord(line[-1]), ord(line[-2]), ord(line[-3])
-                    if self.reactive:
-                        line += ',onos-app-fwd'
-                    line += '\n'
+                    # 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 /opt/onos' )
+        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():
@@ -111,7 +156,7 @@
         # Connect everything to a single switch
         cs0 = self.addSwitch( 'cs0' )
         # Add hosts which will serve as data network controllers
-        for i in range( 0, n ):
+        for i in range( 1, n+1 ):
             c = self.addHost( 'c%s' % i, cls=dataController,
                               inNamespace=True )
             self.addLink( c, cs0 )
@@ -122,7 +167,7 @@
 
 class ONOSCluster( Controller ):
     # TODO
-    n = 4
+    n = 3
    
     def start( self ):
         ctopo = ControlNetwork( n=self.n, dataController=ONOS )
@@ -137,6 +182,9 @@
                 host.start()
 
     def stop( self ):
+        for host in self.cnet.hosts:
+            if isinstance( host, Controller ):
+                host.stop()
         self.cnet.stop()
         
     def clist( self ):
@@ -158,10 +206,11 @@
 
 if __name__ == '__main__':
     # Simple test for ONOS() controller class
-    setLogLevel( 'info' )
+    setLogLevel( 'info' ) #TODO info
     size = 2 if len( argv ) != 2 else int( argv[ 1 ] )
     net = Mininet( topo=LinearTopo( size ),
-                   controller=partial( ONOSCluster, n=4 ),
+                   #controller=ONOS,
+                   controller=partial( ONOSCluster, n=3 ), #TODO
                    switch=OVSSwitchONOS )
     net.start()
     #waitConnected( net.switches )