Merge "Initial implementation of test suite for ONOS NETCONF functionality using OF-Config -for more information please check the README"
diff --git a/TestON/tests/FUNCnetconf/Dependency/netconf.py b/TestON/tests/FUNCnetconf/Dependency/netconf.py
new file mode 100644
index 0000000..5ebbea5
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/netconf.py
@@ -0,0 +1,141 @@
+"""
+ Wrapper functions for FUNCnetconf
+ This functions include Onosclidriver and Mininetclidriver driver functions
+ Author: Jeremy Songster, jeremy@onlab.us
+"""
+import time
+import json
+
+def __init__( self ):
+ self.default = ''
+
+def startApp( main ):
+ """
+ This function starts the netconf app in all onos nodes and ensures that
+ the OF-Config server is running on the node to be configured
+ """
+
+ startResult = main.FALSE
+ startResult = main.CLIs[ 0 ].activateApp( appName="org.onosproject.netconf" )
+ return startResult
+
+def startOFC( main ):
+ """
+ This function uses pexpect pxssh class to activate the ofc-server daemon on OC2
+ """
+
+ startResult = main.FALSE
+ try:
+ main.ONOSbench.handle.sendline( "" )
+ main.ONOSbench.handle.expect( "\$" )
+ main.ONOSbench.handle.sendline( "ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1 }'" )
+ main.ONOSbench.handle.expect( "\$1 }'" )
+ main.ONOSbench.handle.expect( "\$" )
+ main.configDeviceIp = main.ONOSbench.handle.before
+ main.configDeviceIp = main.configDeviceIp.split()
+ main.configDeviceIp = main.configDeviceIp[ 0 ]
+ main.log.info( "Device to be configured: " + str( main.configDeviceIp ) )
+ main.ONOSbench.handle.sendline( "sudo ofc-server" )
+ main.ONOSbench.handle.expect( "\$" )
+ startResult = main.TRUE
+ return startResult
+ except pexpect.ExceptionPexpect as e:
+ main.log.exception( self.name + ": Pexpect exception found: " )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanup()
+ main.exit()
+
+def createConfig( main ):
+ """
+ This function writes a configuration file that can later be sent to the
+ REST API to configure a device.
+ The controller device is assumed to be OC1
+ The device to be configured is assumed to be OC2
+ """
+ createCfgResult = main.FALSE
+ # TODO, add ability to set Manufacturer, Hardware and Software versions
+ main.cfgJson = '{ "devices":{ "netconf:'+ main.configDeviceIp + ":" +\
+ main.configDevicePort + '":' + '{ "basic":{ "driver":"'+\
+ main.configDriver + '" } } }, "apps": { "' +\
+ main.configApps + '":{ "devices":[ { "name":' +\
+ main.configName + ', "password":' + main.configPass +\
+ ', "ip":"' + main.configDeviceIp + '", "port":' +\
+ main.configPort + '} ] } } }'
+ try:
+ file = open( "/home/admin/OnosSystemTest/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json", 'w' )
+ main.cfgJson = json.loads( main.cfgJson )
+ main.cfgJson = json.dumps( main.cfgJson, sort_keys=True,
+ indent=4, separators=(',', ': '))
+ print main.cfgJson
+ file.write( main.cfgJson )
+ if file:
+ createCfgResult = main.TRUE
+ file.close()
+ return createCfgResult
+ else:
+ main.log.error( "There was an error opening the file")
+ return createCfgResult
+ except:
+ main.log.exception( "There was an error opening the file")
+ return createCfgResult
+
+def sendConfig( main ):
+ """
+ This function prepares the command needed to upload the configuration
+ file to the REST API
+ """
+ ip = main.ONOSip[0]
+ port = 8181
+ url = "/network/configuration"
+ method = "POST"
+ data = main.cfgJson
+ configResult = main.FALSE
+ sendResult = main.CLIs[ 0 ].send( ip=ip, port=port, url=url, method=method, data=data )
+ main.log.info( "Device configuration request response code: " + str( sendResult[ 0 ] ) )
+ if ( 200 <= sendResult[ 0 ] <= 299):
+ configResult = main.TRUE
+ else:
+ configResult = main.FALSE
+
+ return configResult
+
+def devices( main ):
+ """
+ This function get the list of devices from the REST API, the ONOS CLI, and
+ the device-controllers command and check to see that each recognizes the
+ device is configured according to the configuration uploaded above.
+ """
+ availResult = main.FALSE
+ typeResult = main.FALSE
+ addressResult = main.FALSE
+ driverResult = main.FALSE
+ try:
+ apiResult = main.CLIs[ 0 ].devices()
+ cliResult = main.CLIs2[ 0 ].devices()
+
+ apiDict = json.loads( apiResult )
+ cliDict = json.loads( cliResult )
+ apiAnnotations = apiDict[ 0 ].get( "annotations" )
+ cliAnnotations = cliDict[ 0 ].get( "annotations" )
+
+ main.log.info( "API device availability result: " + str( apiDict[ 0 ].get( "available" ) ) )
+ main.log.info( "CLI device availability result: " + str( cliDict[ 0 ].get( "available" ) ) )
+ if apiDict[ 0 ].get( "available" ) == True and cliDict[ 0 ].get( "available" ) == True:
+ availResult = main.TRUE
+ main.log.info( "API device type result: " + apiDict[ 0 ].get( "type" ) )
+ main.log.info( "CLI device type result: " + cliDict[ 0 ].get( "type" ) )
+ if apiDict[ 0 ].get( "type" ) == "SWITCH" and cliDict[ 0 ].get( "type" ) == "SWITCH":
+ typeResult = main.TRUE
+ main.log.info( "API device ipaddress: " + apiAnnotations.get( "ipaddress" ) )
+ main.log.info( "CLI device ipaddress: " + apiAnnotations.get( "ipaddress" ) )
+ if str( apiAnnotations.get( "ipaddress" ) ) == main.configDeviceIp and str( cliAnnotations.get( "ipaddress" ) ) == main.configDeviceIp:
+ addressResult = main.TRUE
+ main.log.info( "API device driver: " + apiAnnotations.get( "driver" ) )
+ main.log.info( "CLI device driver: " + cliAnnotations.get( "driver" ) )
+ if apiAnnotations.get( "driver" ) == main.configDriver and cliAnnotations.get( "driver" ) == main.configDriver:
+ driverResult = main.TRUE
+
+ return availResult and typeResult and addressResult and driverResult
+ except TypeError:
+ main.log.error( "Device was not configured correctly" )
+ return main.FALSE
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json b/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json
new file mode 100644
index 0000000..fc5a231
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json
@@ -0,0 +1,21 @@
+{
+ "apps": {
+ "org.onosproject.netconf": {
+ "devices": [
+ {
+ "ip": "10.128.50.10",
+ "name": "sdn",
+ "password": "rocks",
+ "port": 830
+ }
+ ]
+ }
+ },
+ "devices": {
+ "netconf:10.128.50.10:830": {
+ "basic": {
+ "driver": "ovs-netconf"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/Dependency/startUp.py b/TestON/tests/FUNCnetconf/Dependency/startUp.py
new file mode 100644
index 0000000..bf2a2b6
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/startUp.py
@@ -0,0 +1,38 @@
+"""
+ This wrapper function is use for starting up onos instance
+"""
+
+import time
+import os
+import json
+
+def onosBuild( main, gitBranch ):
+ """
+ This includes pulling ONOS and building it using maven install
+ """
+
+ buildResult = main.FALSE
+
+ # Git checkout a branch of ONOS
+ checkOutResult = main.ONOSbench.gitCheckout( gitBranch )
+ # Does the git pull on the branch that was checked out
+ if not checkOutResult:
+ main.log.warn( "Failed to checked out " + gitBranch +
+ " branch")
+ else:
+ main.log.info( "Successfully checked out " + gitBranch +
+ " branch")
+ gitPullResult = main.ONOSbench.gitPull()
+ if gitPullResult == main.ERROR:
+ main.log.error( "Error pulling git branch" )
+ else:
+ main.log.info( "Successfully pulled " + gitBranch + " branch" )
+
+ # Maven clean install
+ buildResult = main.ONOSbench.cleanInstall()
+
+ return buildResult
+
+
+
+
diff --git a/TestON/tests/FUNCnetconf/Dependency/topo.py b/TestON/tests/FUNCnetconf/Dependency/topo.py
new file mode 100644
index 0000000..b44e3fc
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/topo.py
@@ -0,0 +1,100 @@
+"""
+ These functions can be used for topology comparisons
+"""
+
+import time
+import os
+import json
+
+def getAllDevices( main ):
+ """
+ Return a list containing the devices output from each ONOS node
+ """
+ devices = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].devices,
+ name="devices-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ devices.append( t.result )
+ return devices
+
+def getAllHosts( main ):
+ """
+ Return a list containing the hosts output from each ONOS node
+ """
+ hosts = []
+ ipResult = main.TRUE
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].hosts,
+ name="hosts-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ hosts.append( t.result )
+ return hosts
+
+def getAllPorts( main ):
+ """
+ Return a list containing the ports output from each ONOS node
+ """
+ ports = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].ports,
+ name="ports-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ ports.append( t.result )
+ return ports
+
+def getAllLinks( main ):
+ """
+ Return a list containing the links output from each ONOS node
+ """
+ links = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].links,
+ name="links-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ links.append( t.result )
+ return links
+
+def getAllClusters( main ):
+ """
+ Return a list containing the clusters output from each ONOS node
+ """
+ clusters = []
+ threads = []
+ for i in range( main.numCtrls ):
+ t = main.Thread( target=main.CLIs[i].clusters,
+ name="clusters-" + str( i ),
+ args=[ ] )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ clusters.append( t.result )
+ return clusters
+
+
diff --git a/TestON/tests/FUNCnetconf/FUNCnetconf.params b/TestON/tests/FUNCnetconf/FUNCnetconf.params
new file mode 100644
index 0000000..c0fcc5a
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/FUNCnetconf.params
@@ -0,0 +1,53 @@
+<PARAMS>
+ # CASE - Description
+ # 1 - Variable initialization and optional pull and build ONOS package
+ # 2 - Install ONOS
+ # 100 - Ensure netconf app is running
+ # 200 - Create or modify a configuration file
+ # 300 - Push a configuration file to bring up a device
+ # 400 - Bring down a device (not yet possible)
+
+ <testcases>1,[2,100,200,300]*2</testcases>
+
+ <SCALE>
+ <size>1,3</size>
+ </SCALE>
+
+ <DEPENDENCY>
+ <path> /tests/FUNCnetconf/Dependency/</path>
+ <wrapper1>startUp</wrapper1>
+ <wrapper2>netconf</wrapper2>
+ <wrapper3>topo</wrapper3>
+ <topology></topology>
+ </DEPENDENCY>
+
+ <ENV>
+ <cellApps>drivers,openflow,proxyarp,mobility,netconf</cellApps>
+ </ENV>
+
+ <GIT>
+ <pull>False</pull>
+ <branch>master</branch>
+ </GIT>
+
+ <SLEEP>
+ <startup>20</startup>
+ <upSwitch>10</upSwitch>
+ <topoAttempts>3</topoAttempts>
+ </SLEEP>
+
+ <MININET>
+ <switch>0</switch>
+ <links></links>
+ </MININET>
+
+ <CONFIGURE>
+ <cfgDevicePort>830</cfgDevicePort>
+ <cfgDriver>ovs-netconf</cfgDriver>
+ <cfgApps>org.onosproject.netconf</cfgApps>
+ <cfgName>"sdn"</cfgName>
+ <cfgPass>"rocks"</cfgPass>
+ <cfgAppPort>830</cfgAppPort>
+ </CONFIGURE>
+
+</PARAMS>
diff --git a/TestON/tests/FUNCnetconf/FUNCnetconf.py b/TestON/tests/FUNCnetconf/FUNCnetconf.py
new file mode 100644
index 0000000..ddd1cd8
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/FUNCnetconf.py
@@ -0,0 +1,361 @@
+# Testing the NETCONF protocol within ONOS
+
+class FUNCnetconf:
+
+ def __init__( self ):
+ self.default = ''
+
+ def CASE1( self, main ):
+ import time
+ import imp
+ import re
+
+ """
+ - Construct tests variables
+ - GIT ( optional )
+ - Checkout ONOS master branch
+ - Pull latest ONOS code
+ - Building ONOS ( optional )
+ - Install ONOS package
+ - Build ONOS package
+ """
+
+ main.case( "Constructing test variables and building ONOS package" )
+ main.step( "Constructing test variables" )
+ main.caseExplanation = "This test case is mainly for loading " +\
+ "from params file, and pull and build the " +\
+ " latest ONOS package"
+ stepResult = main.FALSE
+
+ # Test variables
+ try:
+ main.testOnDirectory = re.sub( "(/tests)$", "", main.testDir )
+ main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+ gitBranch = main.params[ 'GIT' ][ 'branch' ]
+ main.dependencyPath = main.testOnDirectory + \
+ main.params[ 'DEPENDENCY' ][ 'path' ]
+ # main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+ main.scale = ( main.params[ 'SCALE' ][ 'size' ] ).split( "," )
+ if main.ONOSbench.maxNodes:
+ main.maxNodes = int( main.ONOSbench.maxNodes )
+ else:
+ main.maxNodes = 0
+ wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
+ wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
+ wrapperFile3 = main.params[ 'DEPENDENCY' ][ 'wrapper3' ]
+ main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
+ main.switchSleep = int( main.params[ 'SLEEP' ][ 'upSwitch' ] )
+ main.checkTopoAttempts = int( main.params[ 'SLEEP' ][ 'topoAttempts' ] )
+ main.numSwitch = int( main.params[ 'MININET' ][ 'switch' ] )
+
+ # Config file parameters
+ main.configDevicePort = main.params[ 'CONFIGURE' ][ 'cfgDevicePort' ]
+ main.configDriver = main.params[ 'CONFIGURE' ][ 'cfgDriver' ]
+ main.configApps = main.params[ 'CONFIGURE' ][ 'cfgApps' ]
+ main.configName = main.params[ 'CONFIGURE' ][ 'cfgName' ]
+ main.configPass = main.params[ 'CONFIGURE' ][ 'cfgPass' ]
+ main.configPort = main.params[ 'CONFIGURE' ][ 'cfgAppPort' ]
+
+ gitPull = main.params[ 'GIT' ][ 'pull' ]
+ main.cellData = {} # for creating cell file
+ main.hostsData = {}
+ main.CLIs = []
+ main.CLIs2 = []
+ main.ONOSip = []
+ main.assertReturnString = '' # Assembled assert return string
+
+ main.ONOSip = main.ONOSbench.getOnosIps()
+ print main.ONOSip
+
+ # Assigning ONOS cli handles to a list
+ for i in range( 1, main.maxNodes + 1 ):
+ main.CLIs.append( getattr( main, 'ONOSrest' + str( i ) ) )
+ main.CLIs2.append( getattr( main, 'ONOScli' + str( i ) ) )
+
+ # -- INIT SECTION, ONLY RUNS ONCE -- #
+ main.startUp = imp.load_source( wrapperFile1,
+ main.dependencyPath +
+ wrapperFile1 +
+ ".py" )
+
+ main.netconfFunction = imp.load_source( wrapperFile2,
+ main.dependencyPath +
+ wrapperFile2 +
+ ".py" )
+
+ main.topo = imp.load_source( wrapperFile3,
+ main.dependencyPath +
+ wrapperFile3 +
+ ".py" )
+
+ # Uncomment out the following if a mininet topology is added
+ # copyResult1 = main.ONOSbench.scp( main.Mininet1,
+ # main.dependencyPath +
+ # main.topology,
+ # main.Mininet1.home + "custom/",
+ # direction="to" )
+
+ if main.CLIs and main.CLIs2:
+ stepResult = main.TRUE
+ else:
+ main.log.error( "Did not properly created list of ONOS CLI handle" )
+ stepResult = main.FALSE
+ except Exception as e:
+ main.log.exception(e)
+ main.cleanup()
+ main.exit()
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully construct " +
+ "test variables ",
+ onfail="Failed to construct test variables" )
+
+ if gitPull == 'True':
+ main.step( "Building ONOS in " + gitBranch + " branch" )
+ onosBuildResult = main.startUp.onosBuild( main, gitBranch )
+ stepResult = onosBuildResult
+ 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" )
+ main.ONOSbench.getVersion( report=True )
+
+ def CASE2( self, main ):
+ """
+ - Set up cell
+ - Create cell file
+ - Set cell file
+ - Verify cell file
+ - Kill ONOS process
+ - Uninstall ONOS cluster
+ - Verify ONOS start up
+ - Install ONOS cluster
+ - Connect to cli
+ """
+
+ # main.scale[ 0 ] determines the current number of ONOS controller
+ main.numCtrls = int( main.scale[ 0 ] )
+
+ main.case( "Starting up " + str( main.numCtrls ) +
+ " node(s) ONOS cluster" )
+ main.caseExplanation = "Set up ONOS with " + str( main.numCtrls ) +\
+ " node(s) ONOS cluster"
+
+
+
+ #kill off all onos processes
+ main.log.info( "Safety check, killing all ONOS processes" +
+ " before initiating environment setup" )
+
+
+
+ time.sleep( main.startUpSleep )
+ main.step( "Uninstalling ONOS package" )
+ onosUninstallResult = main.TRUE
+ for ip in main.ONOSip:
+ onosUninstallResult = onosUninstallResult and \
+ main.ONOSbench.onosUninstall( nodeIp=ip )
+ stepResult = onosUninstallResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully uninstalled ONOS package",
+ onfail="Failed to uninstall ONOS package" )
+
+ for i in range( main.maxNodes ):
+ main.ONOSbench.onosDie( main.ONOSip[ i ] )
+
+ main.log.info( "NODE COUNT = " + str( main.numCtrls ) )
+
+ tempOnosIp = []
+ for i in range( main.numCtrls ):
+ tempOnosIp.append( main.ONOSip[i] )
+
+ main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
+ "temp", main.Mininet1.ip_address,
+ main.apps, tempOnosIp )
+
+ main.step( "Apply cell to environment" )
+ cellResult = main.ONOSbench.setCell( "temp" )
+ 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" )
+
+ time.sleep( main.startUpSleep )
+ main.step( "Installing ONOS package" )
+ onosInstallResult = main.TRUE
+ for i in range( main.numCtrls ):
+ onosInstallResult = onosInstallResult and \
+ main.ONOSbench.onosInstall( node=main.ONOSip[ i ], options="" )
+ stepResult = onosInstallResult
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully installed ONOS package",
+ onfail="Failed to install ONOS package" )
+
+ time.sleep( main.startUpSleep )
+ 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" )
+
+ # Start an ONOS cli to provide functionality that is not currently
+ # supported by the Rest API remove this when Leader Checking is supported
+ # by the REST API
+
+ main.step( "Start ONOS cli" )
+ cliResult = main.TRUE
+ for i in range( main.numCtrls ):
+ cliResult = cliResult and \
+ main.CLIs2[ 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" )
+
+ # Remove the first element in main.scale list
+ main.scale.remove( main.scale[ 0 ] )
+
+ def CASE100( self, main ):
+ """
+ Start NETCONF app and OFC-Server or make sure that they are already running
+ """
+ assert main, "There is no main"
+ assert main.CLIs, "There is no main.CLIs"
+ assert main.numCtrls, "Placed the total number of switch topology in \
+ main.numCtrls"
+
+ testResult = main.FALSE
+ main.testName = "Start up NETCONF app in all nodes"
+ main.case( main.testName + " Test - " + str( main.numCtrls ) +
+ " NODE(S)" )
+ main.step( "Starting NETCONF app" )
+ main.assertReturnString = "Assertion result for starting NETCONF app"
+ testResult = main.netconfFunction.startApp( main )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=testResult,
+ onpass=main.assertReturnString,
+ onfail=main.assertReturnString )
+
+ main.step( "Starting OFC-Server" )
+ main.assertReturnString = "Assertion result for starting OFC-Server"
+ testResult = main.netconfFunction.startOFC( main )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=testResult,
+ onpass=main.assertReturnString,
+ onfail=main.assertReturnString )
+ time.sleep( main.startUpSleep )
+
+ def CASE200( self, main ):
+ """
+ Create or modify a Configuration file
+ -The file is built from information loaded from the .params file
+ """
+ assert main, "There is no main"
+ assert main.CLIs, "There is no main.CLIs"
+ assert main.numCtrls, "Placed the total number of switch topology in \
+ main.numCtrls"
+
+ main.testName = "Assemble the configuration"
+ main.case( main.testName + " Test - " + str( main.numCtrls ) +
+ " NODES(S)" )
+ main.step( "Assembling configuration file" )
+ main.assertReturnString = "Assertion result for assembling configuration file"
+ testResult = main.FALSE
+ testResult = main.netconfFunction.createConfig( main )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=testResult,
+ onpass=main.assertReturnString,
+ onfail=main.assertReturnString )
+ time.sleep( main.startUpSleep )
+
+ def CASE300( self, main ):
+ """
+ Push a configuration and bring up a switch
+ """
+ assert main, "There is no main"
+ assert main.CLIs, "There is no main.CLIs"
+ assert main.numCtrls, "Placed the total number of switch topology in \
+ main.numCtrls"
+
+ main.testName = "Uploading the configuration"
+ main.case( main.testName + " Test - " + str( main.numCtrls ) +
+ " NODES(S)" )
+ main.step( "Sending the configuration file")
+ main.assertReturnString = "Assertion result for sending the configuration file"
+ testResult = main.FALSE
+
+ testResult = main.netconfFunction.sendConfig( main )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=testResult,
+ onpass=main.assertReturnString,
+ onfail=main.assertReturnString )
+
+ time.sleep( main.switchSleep )
+
+ main.step( "Confirming the device was configured" )
+ main.assertReturnString = "Assertion result for confirming a configuration."
+ testResult = main.FALSE
+
+ testResult = main.netconfFunction.devices( main )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=testResult,
+ onpass=main.assertReturnString,
+ onfail=main.assertReturnString )
+
+ def CASE400( self, main ):
+ """
+ Bring down a switch
+ This test case is not yet possible, but the functionality needed to
+ perform it is planned to be added
+ There is a message that is sent "Device () has closed session"
+ when the device disconnects from onos for some reason.
+ Because of the triggers for this message are not practical
+ to activate this will likely not be used to implement the test
+ case at this time
+ Possible ways to do this may include bringing down mininet then checking
+ ONOS to see if it was recongnized the device being disconnected
+ """
diff --git a/TestON/tests/FUNCnetconf/FUNCnetconf.topo b/TestON/tests/FUNCnetconf/FUNCnetconf.topo
new file mode 100644
index 0000000..a5a836f
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/FUNCnetconf.topo
@@ -0,0 +1,87 @@
+<TOPOLOGY>
+ <COMPONENT>
+
+ <ONOSbench>
+ <host>localhost</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ <nodes>3</nodes>
+ </COMPONENTS>
+ </ONOSbench>
+
+ <ONOSrest1>
+ <host>OC1</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest1>
+
+ <ONOSrest2>
+ <host>OC2</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>3</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest2>
+
+ <ONOSrest3>
+ <host>OC3</host>
+ <port>8181</port>
+ <user>onos</user>
+ <password>rocks</password>
+ <type>OnosRestDriver</type>
+ <connect_order>4</connect_order>
+ <COMPONENTS>
+ </COMPONENTS>
+ </ONOSrest3>
+
+ <ONOScli1>
+ <host>localhost</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>5</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOScli1>
+
+ <ONOScli2>
+ <host>localhost</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>6</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOScli2>
+
+ <ONOScli3>
+ <host>localhost</host>
+ <user>admin</user>
+ <password></password>
+ <type>OnosCliDriver</type>
+ <connect_order>7</connect_order>
+ <COMPONENTS> </COMPONENTS>
+ </ONOScli3>
+
+ <Mininet1>
+ <host>OCN</host>
+ <user>admin</user>
+ <password></password>
+ <type>MininetCliDriver</type>
+ <connect_order>8</connect_order>
+ <COMPONENTS>
+ <home>~/mininet/</home>
+ </COMPONENTS>
+ </Mininet1>
+
+ </COMPONENT>
+</TOPOLOGY>
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/README b/TestON/tests/FUNCnetconf/README
new file mode 100644
index 0000000..dbf51c0
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/README
@@ -0,0 +1,29 @@
+Summary:
+ This test suite consists of generic NETCONF protocol testing within ONOS
+ using OF-Config to translate NETCONF requests for OVSDB.
+ The following is an overview of how the NETCONF protocol is tested
+ Steps:
+ - Start NETCONF App in all currently running nodes
+ - Start OF-Config server on device to be configured
+ - Create configuration file
+ - Upload the configuration file to the device to be configured
+ - Verify that the device was configured successfully
+
+Required:
+ Make sure that OF-Config, https://github.com/openvswitch/of-config, is
+ installed on the device that is to be configured, the test assumes this
+ device is the machine running TestON.
+ Ensure that <cfgName> and <cfgPass> in the params file are the username
+ and password required to ssh into the desired machine and account that
+ of-config is to be run on.
+ The netconfConfig.json file contains the configuration that was
+ generated by the test. The test also relies on the existence of this
+ file and will missbehave if it is removed entirely. The contents of the
+ file are overwritten everytime the test suite runs through Test Case 200
+
+TODO:
+Extend configuration to allow for specification of
+ - Vendor name
+ - Hardware version
+ - Software version
+ - Serial Number
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/__init__.py b/TestON/tests/FUNCnetconf/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/__init__.py