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