Initial commit for FuncStartTemplate and  supporting driver changes
diff --git a/TestON/core/teston.py b/TestON/core/teston.py
index db17d8e..b8025c3 100644
--- a/TestON/core/teston.py
+++ b/TestON/core/teston.py
@@ -168,8 +168,10 @@
         if "OC" in self.componentDictionary[component]['host']:
             try: 
                 self.componentDictionary[component]['host'] = os.environ[str( self.componentDictionary[component]['host'])]
-            except: 
-                self.log.error("Missing OC environment variable! Check your environment setup and retry") 
+            except KeyError: 
+                self.log.error("Missing OC environment variable! Check your environment setup and retry")
+            except Exception as inst:
+                self.log.error("Uncaught exception: " + str(inst))
 
         connect_result = driverObject.connect(user_name = self.componentDictionary[component]['user'] if ('user' in self.componentDictionary[component].keys()) else getpass.getuser(),
                                               ip_address= self.componentDictionary[component]['host'] if ('host' in self.componentDictionary[component].keys()) else 'localhost',
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 4108da0..6432e88 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -1899,114 +1899,151 @@
             main.exit()
 
 
-    def getOnosIpFromEnv(self):
+    def getOnosIps(self):
 
         import os
 
-        # returns a list of ip addresses for the onos nodes, will work with up to 7 nodes + OCN and OCI
-        # returns in format [ 'x', OC1 ip, OC2 i... ect. ... , ONN ip ]
+        # reads env for OC variables, also saves file with OC variables. If file and env conflict 
+        # priority goes to env. If file has OCs that are not in the env, the file OCs are used. 
+        # In other words, if the env is set, the test will use those values. 
 
-        ONOSIps = ['x']
+        # returns a list of ip addresses for the onos nodes, will work with up to 7 nodes + OCN and OCI
+        # returns in format [ OC1 ip, OC2 ...ect. , OCN, OCI ]
+
+        envONOSIps = {}
 
         x = 1
         while True:
             try:
                 temp = os.environ[ 'OC' + str(x) ]
-            except: 
+            except KeyError: 
                 break
-            ONOSIps.append(temp) 
+            envONOSIps[ ("OC" + str(x)) ] = temp 
             x += 1 
 
         try: 
             temp = os.environ[ 'OCN' ] 
-        except: 
-            main.log.error("MISSING OCN ENVIRONMENT VARIABLE")
+            envONOSIps[ "OCN" ] = temp
+        except KeyError: 
+            main.log.info("OCN not set in env")
 
-        ONOSIps.append(temp)
-        
         try:
             temp = os.environ[ 'OCI' ]
+            envONOSIps[ "OCI" ] = temp
         except:
-            main.log.error("MISSING OCN ENVIRONMENT VARIABLE")
+            main.log.error("OCI not set in env")
 
-        ONOSIps.append(temp)
-        return ONOSIps
+        print(str(envONOSIps))
+
+        order = [ "OC1", "OC2", "OC3","OC4","OC5","OC6","OC7","OCN","OCI" ]
+        ONOSIps = []
+
+        try: 
+            ipFile = open("myIps","r+")
+            fileONOSIps = ipFile.readlines()
+            ipFile.close()
+
+            print str(fileONOSIps)
+            
+            if str(fileONOSIps) == "[]": 
+                ipFile = open("myIps","w+")
+                for key in envONOSIps:
+                    ipFile.write(key+ "=" + envONOSIps[key] + "\n")
+                ipFile.close()
+                for i in order: 
+                    if i in envONOSIps: 
+                        ONOSIps.append(envONOSIps[i])
+                
+                return ONOSIps 
+
+            else: 
+                fileDict = {}
+                for line in fileONOSIps: 
+                    line = line.replace("\n","")
+                    line = line.split("=") 
+                    key = line[0]
+                    value = line[1]
+                    fileDict[key] = value 
+
+                for x in envONOSIps: 
+                    if x in fileDict: 
+                        if envONOSIps[x] == fileDict[x]: 
+                            continue
+                        else: 
+                            fileDict[x] = envONOSIps[x]
+                    else: 
+                        fileDict[x] = envONOSIps[x]
+
+                ipFile = open("myIps","w+")
+                for key in order: 
+                    if key in fileDict: 
+                        ipFile.write(key + "=" + fileDict[key] + "\n")
+                        ONOSIps.append(fileDict[key]) 
+                ipFile.close()
+
+                return ONOSIps 
+
+        except IOError as a:
+            main.log.error(a) 
+
+        except Exception: 
+            main.log.error(a) 
 
 
-    def onosErrorLog(self, nodeIp):
+    def logReport(self, nodeIp, searchTerms, outputMode="s"):
+        '''
+            - accepts either a list or a string for "searchTerms" these
+              terms will be searched for in the log and have their 
+              instances counted 
 
-        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep WARN"
-        self.handle.sendline(cmd)
-        self.handle.expect(":~")
-        before = (self.handle.before).splitlines()
+            - nodeIp is the ip of the node whos log is to be scanned 
 
-        warnings = []
+            - output modes: 
+                "s" -   Simple. Quiet output mode that just prints 
+                        the occurances of each search term 
 
-        for line in before:
-            if "WARN" in line and "grep" not in line:
-                warnings.append(line)
-                main.warnings[main.warnings[0]+1] = line
-                main.warnings[0] += 1
-                if main.warnings[0] >= 10:
-                    main.warnings[0] = 0
+                "d" -   Detailed. Prints occurances as well as the entire
+                        line for each of the last 5 occurances 
+        '''
+        main.log.info("========================== Log Report ===========================\n")
 
-        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep ERROR"
-        self.handle.sendline(cmd)
-        self.handle.expect(":~")
-        before = (self.handle.before).splitlines()
+        if type(searchTerms) is str: 
+            searchTerms = [searchTerms]
 
-        errors = []
+        logLines = [ [" "] for i in range(len(searchTerms)) ]
 
-        for line in before:
-            if "ERROR" in line and "grep" not in line:
-                errors.append(line)
-                main.errors[main.errors[0]+1] = line
-                main.errors[0] += 1
-                if main.errors[0] >= 10:
-                    main.errors[0] = 0
+        for term in range(len(searchTerms)): 
+            logLines[term][0] = searchTerms[term]
 
-        cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep Exept"
-        self.handle.sendline(cmd)
-        self.handle.expect(":~")
-        before = (self.handle.before).splitlines()
 
-        exceptions = []
+        for term in range(len(searchTerms)): 
+            cmd = "onos-ssh " + nodeIp + " cat /opt/onos/log/karaf.log | grep " + searchTerms[term] 
+            self.handle.sendline(cmd)
+            self.handle.expect(":~")
+            before = (self.handle.before).splitlines()
 
-        for line in before:
-            if "Except" in line and "grep" not in line:
-                exceptions.append(line)
-                main.exceptions[main.errors[0]+1] = line
-                main.exceptions[0] += 1
-                if main.exceptions[0] >= 10:
-                    main.exceptions[0] = 0
+            count = [searchTerms[term],0]
 
-        ################################################################
+            for line in before:
+                if searchTerms[term] in line and "grep" not in line:
+                    count[1] += 1 
+                    if before.index(line) > ( len(before) - 7 ):
+                        logLines[term].append(line)
 
-        msg1 = "WARNINGS: \n"
-        for i in main.warnings:
-            if type(i) is not int:
-                msg1 += ( i + "\n")
-
-        msg2 = "ERRORS: \n"
-        for i in main.errors:
-            if type(i) is not int:
-                msg2 += ( i + "\n")
-
-        msg3 = "EXCEPTIONS: \n"
-        for i in main.exceptions:
-            if type(i) is not int:
-                msg3 += ( i + "\n")
-
-        main.log.info("===============================================================\n")
-        main.log.info( "Warnings: " + str(len(warnings)))
-        main.log.info( "Errors: " + str(len(errors)))
-        main.log.info( "Exceptions: " + str(len(exceptions)) + "\n" )
-        if len(warnings) > 0:
-            main.log.info(msg1)
-        if len(errors) > 0:
-            main.log.info(msg2)
-        if len(exceptions) > 0:
-            main.log.info(msg3)
-        main.log.info("===============================================================\n")
+            main.log.info( str(count[0]) + ": " + str(count[1]) )
+            if term == len(searchTerms)-1: 
+                print("\n")
+            
+        if outputMode != "s" and outputMode != "S":        
+            outputString = ""
+            for i in logLines:
+                outputString = i[0] + ": \n" 
+                for x in range(1,len(i)): 
+                    outputString += ( i[x] + "\n" )    
+                
+                if outputString != (i[0] + ": \n"):
+                    main.log.info(outputString) 
+                
+        main.log.info("================================================================\n")
     
 
diff --git a/TestON/tests/FuncStartTemplate/FuncStartTemplate.params b/TestON/tests/FuncStartTemplate/FuncStartTemplate.params
new file mode 100755
index 0000000..a4c2a6e
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.params
@@ -0,0 +1,34 @@
+<PARAMS>
+
+    <testcases>10,9,10,9</testcases>
+    
+    <SCALE>3,1</SCALE>
+    <availableNodes>3</availableNodes>
+    <ENV>
+        <cellName>single_func</cellName>
+        <cellApps>drivers,openflow,proxyarp,mobility</cellApps>
+    </ENV>
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+    <CTRL>
+        <num>3</num>
+        <ip1>OC1</ip1>
+        <port1>6633</port1>
+        <ip2>OC2</ip2>
+        <port2>6633</port2>
+        <ip3>OC3</ip3>
+        <port3>6633</port3>
+    </CTRL>
+    <BENCH>
+        <user>admin</user>
+        <ip1>10.128.5.55</ip1>
+    </BENCH>
+    <MININET>
+        <switch>7</switch>
+        <links>20</links>
+        <topo>~/mininet/custom/newFuncTopo.py</topo>
+    </MININET>
+
+</PARAMS>
diff --git a/TestON/tests/FuncStartTemplate/FuncStartTemplate.py b/TestON/tests/FuncStartTemplate/FuncStartTemplate.py
new file mode 100644
index 0000000..4beefae
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.py
@@ -0,0 +1,231 @@
+
+# Testing the basic functionality of ONOS Next
+# For sanity and driver functionality excercises only.
+
+import time
+import json
+
+time.sleep( 1 )
+
+class FuncStartTemplate:
+
+    def __init__( self ):
+        self.default = ''
+
+    def CASE10( self, main ):
+        import time
+        import os
+        """
+        Startup sequence:
+        cell <name>
+        onos-verify-cell
+        onos-remove-raft-log
+        git pull
+        mvn clean install
+        onos-package
+        onos-install -f
+        onos-wait-for-start
+        """
+        global init
+        global globalONOSip
+        try:
+            if type(init) is not bool:
+                init = False
+        except NameError:
+            init = False
+
+        #Local variables
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        apps = main.params[ 'ENV' ][ 'cellApps' ]
+        gitBranch = main.params[ 'GIT' ][ 'branch' ]
+        benchIp = os.environ[ 'OCN' ]
+        benchUser = main.params[ 'BENCH' ][ 'user' ]
+        topology = main.params[ 'MININET' ][ 'topo' ]
+        main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
+        main.numLinks = int( main.params[ 'MININET' ][ 'links' ] )
+        main.numCtrls = main.params[ 'CTRL' ][ 'num' ]
+        PULLCODE = False
+        if main.params[ 'GIT' ][ 'pull' ] == 'True':
+            PULLCODE = True
+        main.case( "Setting up test environment" )
+        main.CLIs = []
+        for i in range( 1, int( main.numCtrls ) + 1 ):
+            main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
+
+        # -- INIT SECTION, ONLY RUNS ONCE -- #
+        if init == False:
+            init = True
+
+            main.ONOSport = []
+            main.scale = ( main.params[ 'SCALE' ] ).split( "," )
+            main.numCtrls = int( main.scale[ 0 ] )
+
+            if PULLCODE:
+                main.step( "Git checkout and pull " + gitBranch )
+                main.ONOSbench.gitCheckout( gitBranch )
+                gitPullResult = main.ONOSbench.gitPull()
+                if gitPullResult == main.ERROR:
+                    main.log.error( "Error pulling git branch" )
+                main.step( "Using mvn clean & install" )
+                cleanInstallResult = main.ONOSbench.cleanInstall()
+                stepResult = cleanInstallResult
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=stepResult,
+                                         onpass="Successfully compiled " +
+                                                "latest ONOS",
+                                         onfail="Failed to compile " +
+                                                "latest ONOS" )
+            else:
+                main.log.warn( "Did not pull new code so skipping mvn " +
+                               "clean install" )
+
+            globalONOSip = main.ONOSbench.getOnosIps()
+        
+        maxNodes = ( len(globalONOSip) - 2 )
+
+        main.numCtrls = int( main.scale[ 0 ] )
+        main.scale.remove( main.scale[ 0 ] )
+
+        main.ONOSip = []
+        for i in range( maxNodes ): 
+            main.ONOSip.append( globalONOSip[i] )
+
+
+        
+        #kill off all onos processes
+        main.log.info( "Safety check, killing all ONOS processes" +
+                       " before initiating enviornment setup" )
+        for i in range(maxNodes):
+            main.ONOSbench.onosDie( globalONOSip[ i ] )
+        
+        """
+        main.step( "Apply cell to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully applied cell to " + \
+                                        "environment",
+                                 onfail="Failed to apply cell to environment " )
+        """
+        """main.step( "Removing raft logs" )
+        removeRaftResult = main.ONOSbench.onosRemoveRaftLogs()
+        stepResult = removeRaftResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully removed raft logs",
+                                 onfail="Failed to remove raft logs" )
+        """
+
+        print "NODE COUNT = ", main.numCtrls
+        main.log.info( "Creating cell file" )
+        cellIp = []
+        for i in range( main.numCtrls ):
+            cellIp.append( str( main.ONOSip[ i ] ) )
+        print cellIp
+        main.ONOSbench.createCellFile( benchIp, cellName, "",
+                                       str( apps ), *cellIp )
+
+        main.step( "Apply cell to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully applied cell to " + \
+                                        "environment",
+                                 onfail="Failed to apply cell to environment " )
+
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage()
+        stepResult = packageResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully created ONOS package",
+                                 onfail="Failed to create ONOS package" )
+
+        main.step( "Uninstalling ONOS package" )
+        onosUninstallResult = main.TRUE
+        for i in range( main.numCtrls ):
+            onosUninstallResult = onosUninstallResult and \
+                    main.ONOSbench.onosUninstall( nodeIp=main.ONOSip[ i ] )
+        stepResult = onosUninstallResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully uninstalled ONOS package",
+                                 onfail="Failed to uninstall ONOS package" )
+        time.sleep( 5 )
+        main.step( "Installing ONOS package" )
+        onosInstallResult = main.TRUE
+        for i in range( main.numCtrls ):
+            onosInstallResult = onosInstallResult and \
+                    main.ONOSbench.onosInstall( node=main.ONOSip[ i ] )
+        stepResult = onosInstallResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully installed ONOS package",
+                                 onfail="Failed to install ONOS package" )
+
+        time.sleep( 20 )
+        main.step( "Starting ONOS service" )
+        stopResult = main.TRUE
+        startResult = main.TRUE
+        onosIsUp = main.TRUE
+        for i in range( main.numCtrls ):
+            onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
+        if onosIsUp == main.TRUE:
+            main.log.report( "ONOS instance is up and ready" )
+        else:
+            main.log.report( "ONOS instance may not be up, stop and " +
+                             "start ONOS again " )
+            for i in range( main.numCtrls ):
+                stopResult = stopResult and \
+                        main.ONOSbench.onosStop( main.ONOSip[ i ] )
+            for i in range( main.numCtrls ):
+                startResult = startResult and \
+                        main.ONOSbench.onosStart( main.ONOSip[ i ] )
+        stepResult = onosIsUp and stopResult and startResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="ONOS service is ready",
+                                 onfail="ONOS service did not start properly" )
+        
+        main.step( "Start ONOS cli" )
+        cliResult = main.TRUE
+        for i in range( main.numCtrls ):
+            cliResult = cliResult and \
+                        main.CLIs[i].startOnosCli( main.ONOSip[ i ] )
+        stepResult = cliResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully start ONOS cli",
+                                 onfail="Failed to start ONOS cli" )
+    
+    def CASE9( self, main ): 
+        '''
+            Report errors/warnings/exceptions 
+        '''
+        main.log.info("Error report: \n") 
+        main.ONOSbench.logReport( globalONOSip[0], [ "INFO","FOLLOWER","WARN","flow","ERROR","Except" ], "s" )  
+        #main.ONOSbench.logReport( globalONOSip[1], [ "INFO" ], "d" )
+
+    def CASE11( self, main ):
+        """
+            Start mininet
+        """
+        main.log.report( "Start Mininet topology" )
+        main.log.case( "Start Mininet topology" )
+
+        main.step( "Starting Mininet Topology" )
+        topoResult = main.Mininet1.startNet( topoFile=topology )
+        stepResult = topoResult
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass="Successfully loaded topology",
+                                 onfail="Failed to load topology" )
+        # Exit if topology did not load properly
+        if not topoResult:
+            main.cleanup()
+            main.exit()
+
diff --git a/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo b/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo
new file mode 100755
index 0000000..1d14c22
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/FuncStartTemplate.topo
@@ -0,0 +1,52 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS>
+                <home>~/onos</home>
+            </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli1>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+
+        <ONOScli2>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+         <ONOScli3>
+            <host>OCN</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>OnosCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli3>
+
+        <Mininet1>
+            <host>10.128.10.20</host>
+            <user>admin</user>
+            <password>onos_test</password>
+            <type>MininetCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </Mininet1>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/FuncStartTemplate/__init__.py b/TestON/tests/FuncStartTemplate/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FuncStartTemplate/__init__.py