class SCPFbatchFlowResp: | |
''' | |
Testing end-to-end ONOS response time from POST of batched flows to when ONOS returns | |
response confirmation of all flows ADDED; subsequently testing the response time from when REST DELETE to | |
ONOS confirmation of all flows REMOVED. | |
''' | |
def __init__( self ): | |
self.default = '' | |
def CASE1( self, main ): | |
import time | |
import os | |
import imp | |
""" | |
- 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" ) | |
# Test variables | |
main.testOnDirectory = os.path.dirname( os.getcwd ( ) ) | |
main.cellName = main.params[ 'CASE1' ][ 'cellName' ] | |
main.apps = main.params[ 'CASE1' ][ 'cellApps' ] | |
gitBranch = main.params[ 'CASE1' ][ 'gitBranch' ] | |
gitPull = main.params[ 'CASE1' ][ 'gitPull' ] | |
main.maxNodes = int( main.params['GLOBAL'][ 'maxNodes' ] ) | |
main.startUpSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'startup' ] ) | |
main.startMNSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'startMN' ] ) | |
main.addFlowSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'addFlow' ] ) | |
main.delFlowSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'delFlow' ] ) | |
main.chkFlowSleep = float( main.params['GLOBAL']['SLEEP']['chkFlow']) | |
main.cfgSleep = float( main.params['GLOBAL']['SLEEP']['cfg']) | |
main.numSw = int( main.params['GLOBAL']['numSw']) | |
main.numThreads = int( main.params['GLOBAL']['numThreads'] ) | |
main.cellData = {} # for creating cell file | |
main.CLIs = [] | |
main.ONOSip = [] | |
main.ONOSip = main.ONOSbench.getOnosIps() | |
main.commit = main.ONOSbench.getVersion() | |
main.cluster = main.params['GLOBAL']['cluster'] | |
# Assigning ONOS cli handles to a list | |
for i in range( 1, main.maxNodes + 1 ): | |
main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) ) | |
if main.CLIs: | |
stepResult = main.TRUE | |
else: | |
main.log.error( "Did not properly created list of ONOS CLI handle" ) | |
stepResult = main.FALSE | |
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" ) | |
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.numCtrls = int( main.maxNodes ) | |
main.case( "Starting up " + str( main.numCtrls ) + | |
" node(s) ONOS cluster" ) | |
main.log.info( "Safety check, killing all ONOS processes" + | |
" before initiating environment setup" ) | |
tempOnosIp = [] | |
for i in range( main.numCtrls ): | |
tempOnosIp.append( main.ONOSip[i] ) | |
if main.params['CASE2']['incPackaging'] == "true": | |
main.step("Create onos cell file with: " + main.apps) | |
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(opTimeout=240) | |
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( "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( main.startUpSleep ) | |
else: | |
main.log.info("onos Packaging Skipped!") | |
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( 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" ) | |
main.step( "Start ONOS cli" ) | |
cliResult = main.TRUE | |
for i in range( i, main.numCtrls ): | |
cliResult = cliResult and \ | |
main.CLIs[ i ].startOnosCli( ONOSIp=main.ONOSip[ i ] ) | |
main.log.info("ONOSip is: " + 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 CASE10( self, main ): | |
''' | |
Start Mininet | |
''' | |
import time | |
main.case( "Enable openflow-base on onos and start Mininet." ) | |
main.step("Activate openflow-base App") | |
app = main.params['CASE10']['app'] | |
stepResult = main.ONOSbench.onosCli( ONOSIp = main.ONOSip[0], | |
cmdstr = "app activate " + app ) | |
time.sleep(main.cfgSleep) | |
main.log.info(stepResult) | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="Successfully activate " + app, | |
onfail="Failed to activate app " + app ) | |
time.sleep(main.cfgSleep) | |
main.step( "Disable AdaptiveFlowSampling ") | |
stepResult = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.of.flow.impl.OpenFlowRuleProvider", | |
"adaptiveFlowSampling " + main.params['CASE10']['adaptiveFlowenabled']) | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="App Configuration Succeeded! ", | |
onfail="App Configuration Failed!" ) | |
time.sleep(main.cfgSleep) | |
main.step( "Setup Mininet Linear Topology with " + str(main.numSw) + " switches" ) | |
argStr = main.params['CASE10']['mnArgs'].format(main.numSw) | |
stepResult = main.Mininet1.startNet( args = argStr ) | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="Successfully loaded topology", | |
onfail="Failed to load topology" ) | |
time.sleep( main.startMNSleep ) | |
main.step( "Assign switches to controller" ) | |
for i in range(1, main.numSw + 1): | |
main.Mininet1.assignSwController( "s" + str(i), main.ONOSip[0] ) | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="Successfully assigned switch to controller", | |
onfail="Failed to assign switch to controller" ) | |
main.deviceIdPrefix = "of:" | |
time.sleep( main.startMNSleep ) | |
def CASE11( self, main ): | |
''' | |
Start Null Provider | |
''' | |
import time | |
main.case( "Setup Null Provider for linear Topology" ) | |
main.step("Activate Null Provider App") | |
stepResult = main.ONOSbench.onosCli( ONOSIp = main.ONOSip[0], | |
cmdstr = "app activate org.onosproject.null" ) | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="Successfully activated org.onosproject.null", | |
onfail="Failed to activate org.onosproject.null" ) | |
time.sleep( main.cfgSleep) | |
main.step( "Setup Null Provider Linear Topology with " + str(main.numSw) + " devices." ) | |
r1 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "deviceCount " + str(main.numSw)) | |
r2 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "topoShape " + main.params['CASE11']['nullTopo'] ) | |
r3 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "enabled " + main.params['CASE11']['nullStart']) | |
stepResult = r1 & r2 & r3 | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="App Configuration Succeeded! ", | |
onfail="App Configuration Failed!" ) | |
time.sleep( main.cfgSleep ) | |
main.log.info("Check to make sure null providers are configured correctly.") | |
main.ONOSbench.handle.sendline("onos $OC1 summary") | |
stepResult = main.ONOSbench.handle.expect(":~") | |
main.log.info("ONOS Summary: " + main.ONOSbench.handle.before) | |
main.deviceIdPrefix = "null:" | |
time.sleep( main.startMNSleep ) | |
def CASE1000( self, main ): | |
''' | |
create JSON object with batched flows | |
''' | |
import numpy | |
import time | |
from pprint import pprint | |
main.case( "Create a json object for the batched flows" ) | |
main.step( "Parse batch creation information" ) | |
main.batchSize = int(main.params['CASE1000']['batchSize']) | |
main.log.info("Number of flows in a batch is:" + str(main.batchSize)) | |
main.flowJsonBatchList = [] | |
startSw = 1 | |
main.step("Creating a full list of batches") | |
for index in range(1, int(main.params['CASE1000']['batches']) + 1): | |
if startSw <= main.numSw: | |
ind = startSw | |
else: | |
startSw = 1 | |
ind = startSw | |
main.log.info("Creating batch: " + str(index)) | |
flowJsonBatch = main.ONOSrest.createFlowBatch( numSw = main.numSw, | |
swIndex = ind, | |
batchSize = main.batchSize, | |
batchIndex = index, | |
deviceIdpreFix=main.deviceIdPrefix, | |
ingressPort = 2, | |
egressPort = 3) | |
main.flowJsonBatchList.append(flowJsonBatch) | |
startSw += 1 | |
main.log.info( "Number of items created in the batch list is: " + str(len(main.flowJsonBatchList))) | |
def CASE2100(self, main): | |
''' | |
Posting flow batches using threads | |
''' | |
main.case("Using REST API /flows/{} to post flow batch - multi-threads") | |
main.step("Using REST API /flows/{} to post flow batch - multi-threads") | |
from Queue import Queue | |
from threading import Thread | |
import time | |
import json | |
main.threadID = 0 | |
main.addedBatchList = [] | |
q = Queue() | |
tAllAdded = 0 | |
def postWorker(id): | |
while True: | |
item = q.get() | |
#print json.dumps(item) | |
status,response = main.ONOSrest.sendFlowBatch(batch = item) | |
main.log.info("Thread {} is working on posting. ".format(id)) | |
#print json.dumps(response) | |
main.addedBatchList.append(response[1]) | |
q.task_done() | |
for i in range( int( main.params['CASE2100']['numThreads'])): | |
threadID = "ThreadID-" + str(i) | |
t = Thread(target = postWorker, name = threadID, args=(threadID,) ) | |
t.daemon = True | |
t.start() | |
tStartPost = time.time() | |
for item in main.flowJsonBatchList: | |
q.put(item) | |
q.join() | |
tLastPostEnd = time.time() | |
main.step("Check to ensure all flows are in added state.") | |
#pprint(main.addedBatchList) | |
resp = main.FALSE | |
while resp != main.TRUE and ( tAllAdded - tLastPostEnd < int (main.params['CASE2100']['chkFlowTO']) ): | |
if main.params['CASE2100']['RESTchkFlow'] == main.TRUE: | |
resp = main.ONOSrest.checkFlowsState() | |
else: | |
handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False) | |
main.log.info("handle returns PENDING flows: " + handle) | |
if handle == "0": | |
resp = main.TRUE | |
time.sleep( main.chkFlowSleep ) | |
tAllAdded = time.time() | |
if tAllAdded - tLastPostEnd >= int (main.params['CASE2100']['chkFlowTO']): | |
main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllAdded - tLastPostEnd)) | |
main.numFlows = int(main.params['CASE1000']['batches']) *\ | |
int(main.params['CASE1000']['batchSize']) | |
main.log.info("Total number of flows: " + str (main.numFlows) ) | |
main.elapsePOST = tLastPostEnd-tStartPost | |
main.log.info("Total POST elapse time: " + str( main.elapsePOST ) ) | |
main.log.info("Rate of ADD Controller response: " + str(main.numFlows / ( main.elapsePOST ))) | |
main.POSTtoCONFRM = tAllAdded - tLastPostEnd | |
main.log.info("Elapse time from end of last REST POST to Flows in ADDED state: " +\ | |
str( main.POSTtoCONFRM )) | |
main.log.info("Rate of Confirmed Batch Flow ADD is (flows/sec): " + | |
str( main.numFlows / main.POSTtoCONFRM )) | |
main.log.info("Number of flow Batches in the addedBatchList is: " + | |
str( len(main.addedBatchList))) | |
def CASE3100(self, main): | |
''' | |
DELETE flow batches using threads | |
''' | |
main.case("Using REST API /flows/{} to delete flow batch - multi-threads") | |
main.step("Using REST API /flows/{} to delete flow batch - multi-threads") | |
from Queue import Queue | |
from threading import Thread | |
import time | |
import json | |
main.threadID = 0 | |
q = Queue() | |
tAllRemoved = 0 | |
main.log.info("Number of flow batches at start of remove: " + str( len( main.addedBatchList))) | |
def removeWorker(id): | |
while True: | |
item = q.get() | |
response = main.ONOSrest.removeFlowBatch(batch = json.loads(item) ) | |
main.log.info("Thread {} is working on deleting. ".format(id)) | |
q.task_done() | |
for i in range( int( main.params['CASE2100']['numThreads'])): | |
threadID = "ThreadID-" + str(i) | |
t = Thread(target = removeWorker, name = threadID, args=(threadID,) ) | |
t.daemon = True | |
t.start() | |
tStartDelete = time.time() | |
for item in main.addedBatchList: | |
q.put(item) | |
q.join() | |
tLastDeleteEnd = time.time() | |
main.log.info("Number of flow batches at end of remove: " + str( len( main.addedBatchList))) | |
main.step("Check to ensure all flows are in added state.") | |
#pprint(main.addedBatchList) | |
resp = main.FALSE | |
while resp != main.TRUE and ( tAllRemoved - tLastDeleteEnd < int (main.params['CASE3100']['chkFlowTO']) ): | |
if main.params['CASE3100']['RESTchkFlow'] == main.TRUE: | |
resp = main.ONOSrest.checkFlowsState() | |
else: | |
handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False) | |
main.log.info("handle returns PENDING flows: " + handle) | |
if handle == "0": | |
resp = main.TRUE | |
time.sleep( main.chkFlowSleep ) | |
tAllRemoved = time.time() | |
if tLastDeleteEnd - tLastDeleteEnd >= int (main.params['CASE2100']['chkFlowTO']): | |
main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllRemoved - tLastDeleteEnd)) | |
main.numFlows = int(main.params['CASE1000']['batches']) *\ | |
int(main.params['CASE1000']['batchSize']) | |
main.log.info("Total number of flows: " + str (main.numFlows) ) | |
main.elapseDELETE = tLastDeleteEnd-tStartDelete | |
main.log.info("Total DELETE elapse time: " + str( main.elapseDELETE )) | |
main.log.info("Rate of DELETE Controller response: " + str(main.numFlows / ( main.elapseDELETE ))) | |
main.DELtoCONFRM = tAllRemoved - tLastDeleteEnd | |
main.log.info("Elapse time from end of last REST DELETE to Flows in REMOVED state: " +\ | |
str( main.DELtoCONFRM )) | |
main.log.info("Rate of Confirmed Batch Flow REMOVED is (flows/sec): " + str( main.numFlows / main.DELtoCONFRM)) | |
def CASE100(self,main): | |
from pprint import pprint | |
main.case( "Check to ensure onos flows." ) | |
resp = main.ONOSrest.checkFlowsState() | |
#pprint(resp) | |
def CASE210(self,main): | |
main.case("Log test results to a data file") | |
main.step("Write test resulted data to a data file") | |
main.scale = main.maxNodes | |
try: | |
dbFileName="/tmp/SCPFbatchFlowRespData" | |
dbfile = open(dbFileName, "w+") | |
temp = "'" + main.commit + "'," | |
temp += "'" + str( main.scale ) + "'," | |
temp += "'" + main.cluster + "'," | |
temp += "'" + str( main.elapsePOST ) + "'," | |
temp += "'" + str( main.POSTtoCONFRM ) + "'," | |
temp += "'" + str ( main.elapseDELETE ) + "'," | |
temp += "'" + str ( main.DELtoCONFRM ) + "'\n" | |
dbfile.write( temp ) | |
dbfile.close() | |
stepResult = main.TRUE | |
except IOError: | |
main.log.warn("Error opening " + dbFileName + " to write results.") | |
stepResult = main.FALSE | |
utilities.assert_equals( expect=main.TRUE, | |
actual=stepResult, | |
onpass="Succeeded to write results to datafile", | |
onfail="Failed to write results to datafile " ) | |
def CASE110( self, main ): | |
''' | |
Report errors/warnings/exceptions | |
''' | |
main.log.info("Error report: \n" ) | |
main.ONOSbench.logReport( main.ONOSip[ 0 ], | |
[ "INFO", | |
"FOLLOWER", | |
"WARN", | |
"flow", | |
"ERROR", | |
"Except" ], | |
"s" ) | |
#main.stop() | |