blob: ca5e2402a0fbf3742046b180158f7ba076b536d3 [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 \
187 main.CLIs[ i ].startOnosCli( ONOSIp=main.ONOSip[ i ] )
188 main.log.info("ONOSip is: " + main.ONOSip[i])
189 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']
207 stepResult = main.ONOSbench.onosCli( ONOSIp = main.ONOSip[0],
208 cmdstr = "app activate " + app )
209 time.sleep(main.cfgSleep)
210 main.log.info(stepResult)
211 utilities.assert_equals( expect=main.TRUE,
212 actual=stepResult,
213 onpass="Successfully activate " + app,
214 onfail="Failed to activate app " + app )
215
216 time.sleep(main.cfgSleep)
217
218
219 main.step( "Disable AdaptiveFlowSampling ")
220 stepResult = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.of.flow.impl.OpenFlowRuleProvider",
221 "adaptiveFlowSampling " + main.params['CASE10']['adaptiveFlowenabled'])
222 utilities.assert_equals( expect=main.TRUE,
223 actual=stepResult,
224 onpass="App Configuration Succeeded! ",
225 onfail="App Configuration Failed!" )
226 time.sleep(main.cfgSleep)
227
228 main.step( "Setup Mininet Linear Topology with " + str(main.numSw) + " switches" )
229 argStr = main.params['CASE10']['mnArgs'].format(main.numSw)
230 stepResult = main.Mininet1.startNet( args = argStr )
231
232 utilities.assert_equals( expect=main.TRUE,
233 actual=stepResult,
234 onpass="Successfully loaded topology",
235 onfail="Failed to load topology" )
236
237 time.sleep( main.startMNSleep )
238
239 main.step( "Assign switches to controller" )
240 for i in range(1, main.numSw + 1):
241 main.Mininet1.assignSwController( "s" + str(i), main.ONOSip[0] )
242
243 utilities.assert_equals( expect=main.TRUE,
244 actual=stepResult,
245 onpass="Successfully assigned switch to controller",
246 onfail="Failed to assign switch to controller" )
247
248 main.deviceIdPrefix = "of:"
249
250 time.sleep( main.startMNSleep )
251
252 def CASE11( self, main ):
253 '''
254 Start Null Provider
255 '''
256 import time
257
258 main.case( "Setup Null Provider for linear Topology" )
259
260 main.step("Activate Null Provider App")
261 stepResult = main.ONOSbench.onosCli( ONOSIp = main.ONOSip[0],
262 cmdstr = "app activate org.onosproject.null" )
263 utilities.assert_equals( expect=main.TRUE,
264 actual=stepResult,
265 onpass="Successfully activated org.onosproject.null",
266 onfail="Failed to activate org.onosproject.null" )
267 time.sleep( main.cfgSleep)
268
269 main.step( "Setup Null Provider Linear Topology with " + str(main.numSw) + " devices." )
270 r1 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "deviceCount " + str(main.numSw))
271 r2 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "topoShape " + main.params['CASE11']['nullTopo'] )
272 r3 = main.ONOSbench.onosCfgSet( main.ONOSip[0], "org.onosproject.provider.nil.NullProviders", "enabled " + main.params['CASE11']['nullStart'])
273 stepResult = r1 & r2 & r3
274 utilities.assert_equals( expect=main.TRUE,
275 actual=stepResult,
276 onpass="App Configuration Succeeded! ",
277 onfail="App Configuration Failed!" )
278 time.sleep( main.cfgSleep )
279
280 main.log.info("Check to make sure null providers are configured correctly.")
281 main.ONOSbench.handle.sendline("onos $OC1 summary")
282 stepResult = main.ONOSbench.handle.expect(":~")
283 main.log.info("ONOS Summary: " + main.ONOSbench.handle.before)
284
285 main.deviceIdPrefix = "null:"
286
287 time.sleep( main.startMNSleep )
288
289
290
291 def CASE1000( self, main ):
292 '''
293 create JSON object with batched flows
294 '''
295 import numpy
296 import time
297 from pprint import pprint
298
299 main.case( "Create a json object for the batched flows" )
300
301 main.step( "Parse batch creation information" )
302 main.batchSize = int(main.params['CASE1000']['batchSize'])
303 main.log.info("Number of flows in a batch is:" + str(main.batchSize))
304
305 main.flowJsonBatchList = []
306 startSw = 1
307
308 main.step("Creating a full list of batches")
309 for index in range(1, int(main.params['CASE1000']['batches']) + 1):
310 if startSw <= main.numSw:
311 ind = startSw
312 else:
313 startSw = 1
314 ind = startSw
315
316 main.log.info("Creating batch: " + str(index))
317 flowJsonBatch = main.ONOSrest.createFlowBatch( numSw = main.numSw,
318 swIndex = ind,
319 batchSize = main.batchSize,
320 batchIndex = index,
321 deviceIdpreFix=main.deviceIdPrefix,
322 ingressPort = 2,
323 egressPort = 3)
324 main.flowJsonBatchList.append(flowJsonBatch)
325
326 startSw += 1
327 main.log.info( "Number of items created in the batch list is: " + str(len(main.flowJsonBatchList)))
328
329 def CASE2100(self, main):
330 '''
331 Posting flow batches using threads
332 '''
333 main.case("Using REST API /flows/{} to post flow batch - multi-threads")
334 main.step("Using REST API /flows/{} to post flow batch - multi-threads")
335
336 from Queue import Queue
337 from threading import Thread
338 import time
339 import json
340
341 main.threadID = 0
342 main.addedBatchList = []
343 q = Queue()
344 tAllAdded = 0
345
346 def postWorker(id):
347 while True:
348 item = q.get()
349 #print json.dumps(item)
350 status,response = main.ONOSrest.sendFlowBatch(batch = item)
351 main.log.info("Thread {} is working on posting. ".format(id))
352 #print json.dumps(response)
353 main.addedBatchList.append(response[1])
354 q.task_done()
355
356 for i in range( int( main.params['CASE2100']['numThreads'])):
357 threadID = "ThreadID-" + str(i)
358 t = Thread(target = postWorker, name = threadID, args=(threadID,) )
359 t.daemon = True
360 t.start()
361
362 tStartPost = time.time()
363 for item in main.flowJsonBatchList:
364 q.put(item)
365
366 q.join()
367 tLastPostEnd = time.time()
368
369 main.step("Check to ensure all flows are in added state.")
370 #pprint(main.addedBatchList)
371 resp = main.FALSE
372 while resp != main.TRUE and ( tAllAdded - tLastPostEnd < int (main.params['CASE2100']['chkFlowTO']) ):
373 if main.params['CASE2100']['RESTchkFlow'] == main.TRUE:
374 resp = main.ONOSrest.checkFlowsState()
375 else:
376 handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False)
377 main.log.info("handle returns PENDING flows: " + handle)
378 if handle == "0":
379 resp = main.TRUE
380
381 time.sleep( main.chkFlowSleep )
382 tAllAdded = time.time()
383
384 if tAllAdded - tLastPostEnd >= int (main.params['CASE2100']['chkFlowTO']):
385 main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllAdded - tLastPostEnd))
386
387 main.numFlows = int(main.params['CASE1000']['batches']) *\
388 int(main.params['CASE1000']['batchSize'])
389 main.log.info("Total number of flows: " + str (main.numFlows) )
390 main.elapsePOST = tLastPostEnd-tStartPost
391 main.log.info("Total POST elapse time: " + str( main.elapsePOST ) )
392 main.log.info("Rate of ADD Controller response: " + str(main.numFlows / ( main.elapsePOST )))
393
394 main.POSTtoCONFRM = tAllAdded - tLastPostEnd
395 main.log.info("Elapse time from end of last REST POST to Flows in ADDED state: " +\
396 str( main.POSTtoCONFRM ))
397 main.log.info("Rate of Confirmed Batch Flow ADD is (flows/sec): " +
398 str( main.numFlows / main.POSTtoCONFRM ))
399 main.log.info("Number of flow Batches in the addedBatchList is: " +
400 str( len(main.addedBatchList)))
401
402 def CASE3100(self, main):
403 '''
404 DELETE flow batches using threads
405 '''
406 main.case("Using REST API /flows/{} to delete flow batch - multi-threads")
407 main.step("Using REST API /flows/{} to delete flow batch - multi-threads")
408
409 from Queue import Queue
410 from threading import Thread
411 import time
412 import json
413
414 main.threadID = 0
415 q = Queue()
416 tAllRemoved = 0
417
418 main.log.info("Number of flow batches at start of remove: " + str( len( main.addedBatchList)))
419 def removeWorker(id):
420 while True:
421 item = q.get()
422 response = main.ONOSrest.removeFlowBatch(batch = json.loads(item) )
423 main.log.info("Thread {} is working on deleting. ".format(id))
424 q.task_done()
425
426 for i in range( int( main.params['CASE2100']['numThreads'])):
427 threadID = "ThreadID-" + str(i)
428 t = Thread(target = removeWorker, name = threadID, args=(threadID,) )
429 t.daemon = True
430 t.start()
431
432 tStartDelete = time.time()
433 for item in main.addedBatchList:
434 q.put(item)
435
436 q.join()
437 tLastDeleteEnd = time.time()
438 main.log.info("Number of flow batches at end of remove: " + str( len( main.addedBatchList)))
439
440 main.step("Check to ensure all flows are in added state.")
441 #pprint(main.addedBatchList)
442 resp = main.FALSE
443 while resp != main.TRUE and ( tAllRemoved - tLastDeleteEnd < int (main.params['CASE3100']['chkFlowTO']) ):
444 if main.params['CASE3100']['RESTchkFlow'] == main.TRUE:
445 resp = main.ONOSrest.checkFlowsState()
446 else:
447 handle = main.CLIs[0].flows(state = " |grep PEND|wc -l", jsonFormat=False)
448 main.log.info("handle returns PENDING flows: " + handle)
449 if handle == "0":
450 resp = main.TRUE
451 time.sleep( main.chkFlowSleep )
452 tAllRemoved = time.time()
453
454 if tLastDeleteEnd - tLastDeleteEnd >= int (main.params['CASE2100']['chkFlowTO']):
455 main.log.warn("ONOS Flows still in pending state after: {} seconds.".format(tAllRemoved - tLastDeleteEnd))
456
457 main.numFlows = int(main.params['CASE1000']['batches']) *\
458 int(main.params['CASE1000']['batchSize'])
459 main.log.info("Total number of flows: " + str (main.numFlows) )
460 main.elapseDELETE = tLastDeleteEnd-tStartDelete
461 main.log.info("Total DELETE elapse time: " + str( main.elapseDELETE ))
462 main.log.info("Rate of DELETE Controller response: " + str(main.numFlows / ( main.elapseDELETE )))
463
464 main.DELtoCONFRM = tAllRemoved - tLastDeleteEnd
465 main.log.info("Elapse time from end of last REST DELETE to Flows in REMOVED state: " +\
466 str( main.DELtoCONFRM ))
467 main.log.info("Rate of Confirmed Batch Flow REMOVED is (flows/sec): " + str( main.numFlows / main.DELtoCONFRM))
468
469 def CASE100(self,main):
470 from pprint import pprint
471
472 main.case( "Check to ensure onos flows." )
473
474 resp = main.ONOSrest.checkFlowsState()
475 #pprint(resp)
476
477 def CASE210(self,main):
478 main.case("Log test results to a data file")
479 main.step("Write test resulted data to a data file")
480 main.scale = main.maxNodes
481
482 try:
483 dbFileName="/tmp/SCPFbatchFlowRespData"
484 dbfile = open(dbFileName, "w+")
485 temp = "'" + main.commit + "',"
486 temp += "'" + str( main.scale ) + "',"
487 temp += "'" + main.cluster + "',"
488 temp += "'" + str( main.elapsePOST ) + "',"
489 temp += "'" + str( main.POSTtoCONFRM ) + "',"
490 temp += "'" + str ( main.elapseDELETE ) + "',"
491 temp += "'" + str ( main.DELtoCONFRM ) + "'\n"
492 dbfile.write( temp )
493 dbfile.close()
494 stepResult = main.TRUE
495 except IOError:
496 main.log.warn("Error opening " + dbFileName + " to write results.")
497 stepResult = main.FALSE
498
499 utilities.assert_equals( expect=main.TRUE,
500 actual=stepResult,
501 onpass="Succeeded to write results to datafile",
502 onfail="Failed to write results to datafile " )
503
504 def CASE110( self, main ):
505 '''
506 Report errors/warnings/exceptions
507 '''
508 main.log.info("Error report: \n" )
509 main.ONOSbench.logReport( main.ONOSip[ 0 ],
510 [ "INFO",
511 "FOLLOWER",
512 "WARN",
513 "flow",
514 "ERROR",
515 "Except" ],
516 "s" )
517 #main.stop()
518