blob: 4aff74d800d099f4c670ccb2eb611f96072a34aa [file] [log] [blame]
suibin zhang17308622016-04-14 15:45:30 -07001class SCPFbatchFlowResp:
2 '''
3 Testing end-to-end ONOS response time from POST of batched flows to when ONOS returns
4 response confirmation of all flows ADDED; subsequently testing the response time from when REST DELETE to
5 ONOS confirmation of all flows REMOVED.
6 '''
7
8 def __init__( self ):
9 self.default = ''
10
11 def CASE1( self, main ):
12 import time
13 import os
14 import imp
15
16 """
17 - Construct tests variables
18 - GIT ( optional )
19 - Checkout ONOS master branch
20 - Pull latest ONOS code
21 - Building ONOS ( optional )
22 - Install ONOS package
23 - Build ONOS package
24 """
25
26 main.case( "Constructing test variables and building ONOS package" )
27 main.step( "Constructing test variables" )
28
29 # Test variables
30 main.testOnDirectory = os.path.dirname( os.getcwd ( ) )
31 main.cellName = main.params[ 'CASE1' ][ 'cellName' ]
32 main.apps = main.params[ 'CASE1' ][ 'cellApps' ]
33 gitBranch = main.params[ 'CASE1' ][ 'gitBranch' ]
34 gitPull = main.params[ 'CASE1' ][ 'gitPull' ]
35 main.maxNodes = int( main.params['GLOBAL'][ 'maxNodes' ] )
36 main.startUpSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'startup' ] )
37 main.startMNSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'startMN' ] )
38 main.addFlowSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'addFlow' ] )
39 main.delFlowSleep = float( main.params['GLOBAL'][ 'SLEEP' ][ 'delFlow' ] )
40 main.chkFlowSleep = float( main.params['GLOBAL']['SLEEP']['chkFlow'])
41 main.cfgSleep = float( main.params['GLOBAL']['SLEEP']['cfg'])
42 main.numSw = int( main.params['GLOBAL']['numSw'])
43 main.numThreads = int( main.params['GLOBAL']['numThreads'] )
44 main.cellData = {} # for creating cell file
45 main.CLIs = []
46 main.ONOSip = []
YPZhang28909bc2016-06-20 13:29:11 -070047
suibin zhang17308622016-04-14 15:45:30 -070048 main.ONOSip = main.ONOSbench.getOnosIps()
49 main.commit = main.ONOSbench.getVersion()
YPZhang28909bc2016-06-20 13:29:11 -070050 main.commit = main.commit.split(" ")[1]
51
suibin zhang17308622016-04-14 15:45:30 -070052 main.cluster = main.params['GLOBAL']['cluster']
53
54 # Assigning ONOS cli handles to a list
55 for i in range( 1, main.maxNodes + 1 ):
56 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
57
58
59 if main.CLIs:
60 stepResult = main.TRUE
61 else:
62 main.log.error( "Did not properly created list of ONOS CLI handle" )
63 stepResult = main.FALSE
64
65 utilities.assert_equals( expect=main.TRUE,
66 actual=stepResult,
67 onpass="Successfully construct " +
68 "test variables ",
69 onfail="Failed to construct test variables" )
70
71 if gitPull == 'True':
72 main.step( "Building ONOS in " + gitBranch + " branch" )
73 onosBuildResult = main.startUp.onosBuild( main, gitBranch )
74 stepResult = onosBuildResult
75 utilities.assert_equals( expect=main.TRUE,
76 actual=stepResult,
77 onpass="Successfully compiled " +
78 "latest ONOS",
79 onfail="Failed to compile " +
80 "latest ONOS" )
81 else:
82 main.log.warn( "Did not pull new code so skipping mvn " +
83 "clean install" )
84
85 def CASE2( self, main ):
86 """
87 - Set up cell
88 - Create cell file
89 - Set cell file
90 - Verify cell file
91 - Kill ONOS process
92 - Uninstall ONOS cluster
93 - Verify ONOS start up
94 - Install ONOS cluster
95 - Connect to cli
96 """
97
98 main.numCtrls = int( main.maxNodes )
99
100 main.case( "Starting up " + str( main.numCtrls ) +
101 " node(s) ONOS cluster" )
102
103 main.log.info( "Safety check, killing all ONOS processes" +
104 " before initiating environment setup" )
105
106 tempOnosIp = []
107 for i in range( main.numCtrls ):
108 tempOnosIp.append( main.ONOSip[i] )
109
110 if main.params['CASE2']['incPackaging'] == "true":
111 main.step("Create onos cell file with: " + main.apps)
112 main.ONOSbench.createCellFile( main.ONOSbench.ip_address, "temp",
113 main.Mininet1.ip_address, main.apps, tempOnosIp )
114
115 main.step( "Apply cell to environment" )
116 cellResult = main.ONOSbench.setCell( "temp" )
117 verifyResult = main.ONOSbench.verifyCell()
118 stepResult = cellResult and verifyResult
119 utilities.assert_equals( expect=main.TRUE,
120 actual=stepResult,
121 onpass="Successfully applied cell to " + \
122 "environment",
123 onfail="Failed to apply cell to environment " )
124
125
126 main.step( "Creating ONOS package" )
127 packageResult = main.ONOSbench.onosPackage(opTimeout=240)
128 stepResult = packageResult
129 utilities.assert_equals( expect=main.TRUE,
130 actual=stepResult,
131 onpass="Successfully created ONOS package",
132 onfail="Failed to create ONOS package" )
133 time.sleep( main.startUpSleep )
134
135 main.step( "Uninstalling ONOS package" )
136 onosUninstallResult = main.TRUE
137 for i in range( main.numCtrls ):
138 onosUninstallResult = onosUninstallResult and \
139 main.ONOSbench.onosUninstall( nodeIp=main.ONOSip[ i ] )
140 stepResult = onosUninstallResult
141 utilities.assert_equals( expect=main.TRUE,
142 actual=stepResult,
143 onpass="Successfully uninstalled ONOS package",
144 onfail="Failed to uninstall ONOS package" )
145 time.sleep( main.startUpSleep )
146
147 else:
148 main.log.info("onos Packaging Skipped!")
149
150 main.step( "Installing ONOS package" )
151 onosInstallResult = main.TRUE
152 for i in range( main.numCtrls ):
153 onosInstallResult = onosInstallResult and \
154 main.ONOSbench.onosInstall( node=main.ONOSip[ i ] )
155 stepResult = onosInstallResult
156 utilities.assert_equals( expect=main.TRUE,
157 actual=stepResult,
158 onpass="Successfully installed ONOS package",
159 onfail="Failed to install ONOS package" )
160 time.sleep( main.startUpSleep )
161
162 main.step( "Starting ONOS service" )
163 stopResult = main.TRUE
164 startResult = main.TRUE
165 onosIsUp = main.TRUE
166
167 for i in range( main.numCtrls ):
168 onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
169 if onosIsUp == main.TRUE:
170 main.log.report( "ONOS instance is up and ready" )
171 else:
172 main.log.report( "ONOS instance may not be up, stop and " +
173 "start ONOS again " )
174 for i in range( main.numCtrls ):
175 stopResult = stopResult and \
176 main.ONOSbench.onosStop( main.ONOSip[ i ] )
177 for i in range( main.numCtrls ):
178 startResult = startResult and \
179 main.ONOSbench.onosStart( main.ONOSip[ i ] )
180 stepResult = onosIsUp and stopResult and startResult
181 utilities.assert_equals( expect=main.TRUE,
182 actual=stepResult,
183 onpass="ONOS service is ready",
184 onfail="ONOS service did not start properly" )
185
186 main.step( "Start ONOS cli" )
187 cliResult = main.TRUE
188 for i in range( i, main.numCtrls ):
189 cliResult = cliResult and \
YPZhang5d0552f2016-05-18 13:02:52 -0700190 main.ONOScli1.startCellCli( )
191 main.log.info("ONOSip is: " + main.ONOScli1.ip_address)
suibin zhang17308622016-04-14 15:45:30 -0700192 stepResult = cliResult
193 utilities.assert_equals( expect=main.TRUE,
194 actual=stepResult,
195 onpass="Successfully start ONOS cli",
196 onfail="Failed to start ONOS cli" )
197
198
199
200 def CASE10( self, main ):
201 '''
202 Start Mininet
203 '''
204 import time
205
206 main.case( "Enable openflow-base on onos and start Mininet." )
207
208 main.step("Activate openflow-base App")
209 app = main.params['CASE10']['app']
YPZhang5d0552f2016-05-18 13:02:52 -0700210 stepResult = main.ONOScli1.activateApp( app )
suibin zhang17308622016-04-14 15:45:30 -0700211 time.sleep(main.cfgSleep)
212 main.log.info(stepResult)
213 utilities.assert_equals( expect=main.TRUE,
214 actual=stepResult,
215 onpass="Successfully activate " + app,
216 onfail="Failed to activate app " + app )
217
218 time.sleep(main.cfgSleep)
219
220
YPZhang5d0552f2016-05-18 13:02:52 -0700221 main.step( "Configure AdaptiveFlowSampling ")
222 stepResult = main.ONOScli1.setCfg( component = "org.onosproject.provider.of.flow.impl.OpenFlowRuleProvider",
223 propName = "adaptiveFlowSampling ", value = main.params['CASE10']['adaptiveFlowenabled'])
suibin zhang17308622016-04-14 15:45:30 -0700224 utilities.assert_equals( expect=main.TRUE,
225 actual=stepResult,
226 onpass="App Configuration Succeeded! ",
227 onfail="App Configuration Failed!" )
228 time.sleep(main.cfgSleep)
229
230 main.step( "Setup Mininet Linear Topology with " + str(main.numSw) + " switches" )
231 argStr = main.params['CASE10']['mnArgs'].format(main.numSw)
232 stepResult = main.Mininet1.startNet( args = argStr )
233
234 utilities.assert_equals( expect=main.TRUE,
235 actual=stepResult,
236 onpass="Successfully loaded topology",
237 onfail="Failed to load topology" )
238
239 time.sleep( main.startMNSleep )
240
241 main.step( "Assign switches to controller" )
242 for i in range(1, main.numSw + 1):
243 main.Mininet1.assignSwController( "s" + str(i), main.ONOSip[0] )
244
245 utilities.assert_equals( expect=main.TRUE,
246 actual=stepResult,
247 onpass="Successfully assigned switch to controller",
248 onfail="Failed to assign switch to controller" )
249
250 main.deviceIdPrefix = "of:"
251
252 time.sleep( main.startMNSleep )
253
254 def CASE11( self, main ):
255 '''
256 Start Null Provider
257 '''
258 import time
259
260 main.case( "Setup Null Provider for linear Topology" )
261
262 main.step("Activate Null Provider App")
263 stepResult = main.ONOSbench.onosCli( ONOSIp = main.ONOSip[0],
264 cmdstr = "app activate org.onosproject.null" )
265 utilities.assert_equals( expect=main.TRUE,
266 actual=stepResult,
267 onpass="Successfully activated org.onosproject.null",
268 onfail="Failed to activate org.onosproject.null" )
269 time.sleep( main.cfgSleep)
270
271 main.step( "Setup Null Provider Linear Topology with " + str(main.numSw) + " devices." )
272 r1 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "deviceCount " + str(main.numSw))
273 r2 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "topoShape " + main.params['CASE11']['nullTopo'] )
274 r3 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "enabled " + main.params['CASE11']['nullStart'])
275 stepResult = r1 & r2 & r3
276 utilities.assert_equals( expect=main.TRUE,
277 actual=stepResult,
278 onpass="App Configuration Succeeded! ",
279 onfail="App Configuration Failed!" )
280 time.sleep( main.cfgSleep )
281
282 main.log.info("Check to make sure null providers are configured correctly.")
283 main.ONOSbench.handle.sendline("onos $OC1 summary")
284 stepResult = main.ONOSbench.handle.expect(":~")
285 main.log.info("ONOS Summary: " + main.ONOSbench.handle.before)
286
287 main.deviceIdPrefix = "null:"
288
289 time.sleep( main.startMNSleep )
290
291
292
293 def CASE1000( self, main ):
294 '''
295 create JSON object with batched flows
296 '''
297 import numpy
298 import time
299 from pprint import pprint
300
301 main.case( "Create a json object for the batched flows" )
302
303 main.step( "Parse batch creation information" )
304 main.batchSize = int(main.params['CASE1000']['batchSize'])
305 main.log.info("Number of flows in a batch is:" + str(main.batchSize))
306
307 main.flowJsonBatchList = []
308 startSw = 1
309
310 main.step("Creating a full list of batches")
311 for index in range(1, int(main.params['CASE1000']['batches']) + 1):
312 if startSw <= main.numSw:
313 ind = startSw
314 else:
315 startSw = 1
316 ind = startSw
317
318 main.log.info("Creating batch: " + str(index))
319 flowJsonBatch = main.ONOSrest.createFlowBatch( numSw = main.numSw,
320 swIndex = ind,
321 batchSize = main.batchSize,
322 batchIndex = index,
323 deviceIdpreFix=main.deviceIdPrefix,
324 ingressPort = 2,
325 egressPort = 3)
326 main.flowJsonBatchList.append(flowJsonBatch)
327
328 startSw += 1
329 main.log.info( "Number of items created in the batch list is: " + str(len(main.flowJsonBatchList)))
330
331 def CASE2100(self, main):
332 '''
333 Posting flow batches using threads
334 '''
335 main.case("Using REST API /flows/{} to post flow batch - multi-threads")
336 main.step("Using REST API /flows/{} to post flow batch - multi-threads")
337
338 from Queue import Queue
339 from threading import Thread
340 import time
341 import json
342
343 main.threadID = 0
344 main.addedBatchList = []
345 q = Queue()
346 tAllAdded = 0
347
348 def postWorker(id):
349 while True:
350 item = q.get()
351 #print json.dumps(item)
352 status,response = main.ONOSrest.sendFlowBatch(batch = item)
353 main.log.info("Thread {} is working on posting. ".format(id))
354 #print json.dumps(response)
355 main.addedBatchList.append(response[1])
356 q.task_done()
357
358 for i in range( int( main.params['CASE2100']['numThreads'])):
359 threadID = "ThreadID-" + str(i)
360 t = Thread(target = postWorker, name = threadID, args=(threadID,) )
361 t.daemon = True
362 t.start()
363
364 tStartPost = time.time()
365 for item in main.flowJsonBatchList:
366 q.put(item)
367
368 q.join()
369 tLastPostEnd = time.time()
370
371 main.step("Check to ensure all flows are in added state.")
372 #pprint(main.addedBatchList)
373 resp = main.FALSE
374 while resp != main.TRUE and ( tAllAdded - tLastPostEnd < int (main.params['CASE2100']['chkFlowTO']) ):
375 if main.params['CASE2100']['RESTchkFlow'] == main.TRUE:
376 resp = main.ONOSrest.checkFlowsState()
377 else:
378 handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False)
379 main.log.info("handle returns PENDING flows: " + handle)
380 if handle == "0":
381 resp = main.TRUE
382
383 time.sleep( main.chkFlowSleep )
384 tAllAdded = time.time()
385
386 if tAllAdded - tLastPostEnd >= int (main.params['CASE2100']['chkFlowTO']):
387 main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllAdded - tLastPostEnd))
388
389 main.numFlows = int(main.params['CASE1000']['batches']) *\
390 int(main.params['CASE1000']['batchSize'])
391 main.log.info("Total number of flows: " + str (main.numFlows) )
392 main.elapsePOST = tLastPostEnd-tStartPost
393 main.log.info("Total POST elapse time: " + str( main.elapsePOST ) )
394 main.log.info("Rate of ADD Controller response: " + str(main.numFlows / ( main.elapsePOST )))
395
396 main.POSTtoCONFRM = tAllAdded - tLastPostEnd
397 main.log.info("Elapse time from end of last REST POST to Flows in ADDED state: " +\
398 str( main.POSTtoCONFRM ))
399 main.log.info("Rate of Confirmed Batch Flow ADD is (flows/sec): " +
400 str( main.numFlows / main.POSTtoCONFRM ))
401 main.log.info("Number of flow Batches in the addedBatchList is: " +
402 str( len(main.addedBatchList)))
403
404 def CASE3100(self, main):
405 '''
406 DELETE flow batches using threads
407 '''
408 main.case("Using REST API /flows/{} to delete flow batch - multi-threads")
409 main.step("Using REST API /flows/{} to delete flow batch - multi-threads")
410
411 from Queue import Queue
412 from threading import Thread
413 import time
414 import json
415
416 main.threadID = 0
417 q = Queue()
418 tAllRemoved = 0
419
420 main.log.info("Number of flow batches at start of remove: " + str( len( main.addedBatchList)))
421 def removeWorker(id):
422 while True:
423 item = q.get()
424 response = main.ONOSrest.removeFlowBatch(batch = json.loads(item) )
425 main.log.info("Thread {} is working on deleting. ".format(id))
426 q.task_done()
427
428 for i in range( int( main.params['CASE2100']['numThreads'])):
429 threadID = "ThreadID-" + str(i)
430 t = Thread(target = removeWorker, name = threadID, args=(threadID,) )
431 t.daemon = True
432 t.start()
433
434 tStartDelete = time.time()
435 for item in main.addedBatchList:
436 q.put(item)
437
438 q.join()
439 tLastDeleteEnd = time.time()
440 main.log.info("Number of flow batches at end of remove: " + str( len( main.addedBatchList)))
441
442 main.step("Check to ensure all flows are in added state.")
443 #pprint(main.addedBatchList)
444 resp = main.FALSE
445 while resp != main.TRUE and ( tAllRemoved - tLastDeleteEnd < int (main.params['CASE3100']['chkFlowTO']) ):
446 if main.params['CASE3100']['RESTchkFlow'] == main.TRUE:
447 resp = main.ONOSrest.checkFlowsState()
448 else:
449 handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False)
450 main.log.info("handle returns PENDING flows: " + handle)
451 if handle == "0":
452 resp = main.TRUE
453 time.sleep( main.chkFlowSleep )
454 tAllRemoved = time.time()
455
456 if tLastDeleteEnd - tLastDeleteEnd >= int (main.params['CASE2100']['chkFlowTO']):
457 main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllRemoved - tLastDeleteEnd))
458
459 main.numFlows = int(main.params['CASE1000']['batches']) *\
460 int(main.params['CASE1000']['batchSize'])
461 main.log.info("Total number of flows: " + str (main.numFlows) )
462 main.elapseDELETE = tLastDeleteEnd-tStartDelete
463 main.log.info("Total DELETE elapse time: " + str( main.elapseDELETE ))
464 main.log.info("Rate of DELETE Controller response: " + str(main.numFlows / ( main.elapseDELETE )))
465
466 main.DELtoCONFRM = tAllRemoved - tLastDeleteEnd
467 main.log.info("Elapse time from end of last REST DELETE to Flows in REMOVED state: " +\
468 str( main.DELtoCONFRM ))
469 main.log.info("Rate of Confirmed Batch Flow REMOVED is (flows/sec): " + str( main.numFlows / main.DELtoCONFRM))
470
471 def CASE100(self,main):
472 from pprint import pprint
473
474 main.case( "Check to ensure onos flows." )
475
476 resp = main.ONOSrest.checkFlowsState()
477 #pprint(resp)
478
479 def CASE210(self,main):
480 main.case("Log test results to a data file")
481 main.step("Write test resulted data to a data file")
482 main.scale = main.maxNodes
483
484 try:
485 dbFileName="/tmp/SCPFbatchFlowRespData"
486 dbfile = open(dbFileName, "w+")
487 temp = "'" + main.commit + "',"
YPZhang28909bc2016-06-20 13:29:11 -0700488 temp += "'1gig',"
suibin zhang17308622016-04-14 15:45:30 -0700489 temp += "'" + str( main.scale ) + "',"
490 temp += "'" + main.cluster + "',"
491 temp += "'" + str( main.elapsePOST ) + "',"
492 temp += "'" + str( main.POSTtoCONFRM ) + "',"
YPZhang28909bc2016-06-20 13:29:11 -0700493 temp += "'" + str( main.numFlows / main.POSTtoCONFRM ) + "',"
suibin zhang17308622016-04-14 15:45:30 -0700494 temp += "'" + str ( main.elapseDELETE ) + "',"
YPZhang28909bc2016-06-20 13:29:11 -0700495 temp += "'" + str ( main.DELtoCONFRM ) + "',"
496 temp += "'" + str( main.numFlows / main.DELtoCONFRM ) + "',"
497 temp += "'" + str( main.numSw ) + "'\n"
suibin zhang17308622016-04-14 15:45:30 -0700498 dbfile.write( temp )
499 dbfile.close()
500 stepResult = main.TRUE
501 except IOError:
502 main.log.warn("Error opening " + dbFileName + " to write results.")
503 stepResult = main.FALSE
504
505 utilities.assert_equals( expect=main.TRUE,
506 actual=stepResult,
507 onpass="Succeeded to write results to datafile",
508 onfail="Failed to write results to datafile " )
509
510 def CASE110( self, main ):
511 '''
512 Report errors/warnings/exceptions
513 '''
514 main.log.info("Error report: \n" )
515 main.ONOSbench.logReport( main.ONOSip[ 0 ],
516 [ "INFO",
517 "FOLLOWER",
518 "WARN",
519 "flow",
520 "ERROR",
521 "Except" ],
522 "s" )
523 #main.stop()
524