blob: 61c12ade8b6cec9ffb70f43cd74b8f14bbcf39b7 [file] [log] [blame]
Jon Hall1efcb3f2016-08-23 13:42:15 -07001import os
2import imp
3import time
4import json
5import urllib
6from core import utilities
7
8
9class Testcaselib:
10 @staticmethod
11 def initTest( main ):
12 """
13 - Construct tests variables
14 - GIT ( optional )
15 - Checkout ONOS master branch
16 - Pull latest ONOS code
17 - Building ONOS ( optional )
18 - Install ONOS package
19 - Build ONOS package
20 """
21 main.step( "Constructing test variables" )
22 # Test variables
23 main.cellName = main.params[ 'ENV' ][ 'cellName' ]
24 main.apps = main.params[ 'ENV' ][ 'cellApps' ]
25 main.diff = main.params[ 'ENV' ][ 'diffApps' ]
26 gitBranch = main.params[ 'GIT' ][ 'branch' ]
27 main.path = os.path.dirname( main.testFile )
28 main.dependencyPath = main.path + "/../dependencies/"
29 main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
30 wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
31 main.scale = (main.params[ 'SCALE' ][ 'size' ]).split( "," )
32 main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
33 # main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
34 main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
35 main.cellData = { } # for creating cell file
36 main.CLIs = [ ]
37 main.ONOSip = [ ]
38 main.RESTs = [ ]
39
40 # Assigning ONOS cli handles to a list
41 for i in range( 1, main.maxNodes + 1 ):
42 main.CLIs.append( getattr( main, 'ONOScli' + str( i ) ) )
43 main.RESTs.append( getattr( main, 'ONOSrest' + str( i ) ) )
44 main.ONOSip.append( main.CLIs[ i - 1 ].ip_address )
45 # -- INIT SECTION, ONLY RUNS ONCE -- #
46 main.startUp = imp.load_source( wrapperFile1,
47 main.dependencyPath +
48 wrapperFile1 +
49 ".py" )
50
51 copyResult1 = main.ONOSbench.scp( main.Mininet1,
52 main.dependencyPath +
53 main.topology,
54 main.Mininet1.home,
55 direction="to" )
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 @staticmethod
69 def installOnos( main, vlanCfg=True ):
70 """
71 - Set up cell
72 - Create cell file
73 - Set cell file
74 - Verify cell file
75 - Kill ONOS process
76 - Uninstall ONOS cluster
77 - Verify ONOS start up
78 - Install ONOS cluster
79 - Connect to cli
80 """
81 # main.scale[ 0 ] determines the current number of ONOS controller
82 apps = main.apps
83 if main.diff:
84 apps = main.apps + "," + main.diff
85 else:
86 main.log.error( "App list is empty" )
87 print "NODE COUNT = ", main.numCtrls
88 print main.ONOSip
89 tempOnosIp = [ ]
90 main.dynamicHosts = [ 'in1', 'out1' ]
91 for i in range( main.numCtrls ):
92 tempOnosIp.append( main.ONOSip[ i ] )
93 onosUser = main.params[ 'ENV' ][ 'cellUser' ]
94 main.step( "Create and Apply cell file" )
95 main.ONOSbench.createCellFile( main.ONOSbench.ip_address,
96 "temp",
97 main.Mininet1.ip_address,
98 apps,
99 tempOnosIp,
100 onosUser,
101 useSSH=True )
102 cellResult = main.ONOSbench.setCell( "temp" )
103 verifyResult = main.ONOSbench.verifyCell( )
104 stepResult = cellResult and verifyResult
105 utilities.assert_equals( expect=main.TRUE,
106 actual=stepResult,
107 onpass="Successfully applied cell to " + \
108 "environment",
109 onfail="Failed to apply cell to environment " )
110 # kill off all onos processes
111 main.log.info( "Safety check, killing all ONOS processes" +
112 " before initiating environment setup" )
113 for i in range( main.maxNodes ):
114 main.ONOSbench.onosDie( main.ONOSip[ i ] )
115 main.step( "Create and Install ONOS package" )
Jon Hallbd60ea02016-08-23 10:03:59 -0700116 packageResult = main.ONOSbench.buckBuild()
Jon Hall1efcb3f2016-08-23 13:42:15 -0700117
118 onosInstallResult = main.TRUE
119 for i in range( main.numCtrls ):
120 onosInstallResult = onosInstallResult and \
121 main.ONOSbench.onosInstall(
122 node=main.ONOSip[ i ] )
123 stepResult = onosInstallResult
124 utilities.assert_equals( expect=main.TRUE,
125 actual=stepResult,
126 onpass="Successfully installed ONOS package",
127 onfail="Failed to install ONOS package" )
128 for i in range( main.numCtrls ):
129 onosInstallResult = onosInstallResult and \
130 main.ONOSbench.onosSecureSSH(
131 node=main.ONOSip[ i ] )
132 stepResult = onosInstallResult
133 utilities.assert_equals( expect=main.TRUE,
134 actual=stepResult,
135 onpass="Successfully secure SSH",
136 onfail="Failed to secure SSH" )
137 main.step( "Starting ONOS service" )
138 stopResult, startResult, onosIsUp = main.TRUE, main.TRUE, main.TRUE,
139 for i in range( main.numCtrls ):
140 onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] )
141 if onosIsUp == main.TRUE:
142 main.log.report( "ONOS instance is up and ready" )
143 else:
144 main.log.report( "ONOS instance may not be up, stop and " +
145 "start ONOS again " )
146 for i in range( main.numCtrls ):
147 stopResult = stopResult and \
148 main.ONOSbench.onosStop( main.ONOSip[ i ] )
149 for i in range( main.numCtrls ):
150 startResult = startResult and \
151 main.ONOSbench.onosStart( main.ONOSip[ i ] )
152 stepResult = onosIsUp and stopResult and startResult
153
154 utilities.assert_equals( expect=main.TRUE,
155 actual=stepResult,
156 onpass="ONOS service is ready",
157 onfail="ONOS service did not start properly" )
158 main.step( "Checking if ONOS CLI is ready" )
159 for i in range( main.numCtrls ):
160 main.CLIs[ i ].startCellCli( )
161 cliResult = main.CLIs[ i ].startOnosCli( main.ONOSip[ i ],
162 commandlineTimeout=60,
163 onosStartTimeout=100 )
164 utilities.assert_equals( expect=main.TRUE,
165 actual=cliResult,
166 onpass="ONOS CLI is ready",
167 onfail="ONOS CLI is not ready" )
168 main.active = 0
169 for i in range( 10 ):
170 ready = True
171 output = main.CLIs[ main.active ].summary( )
172 if not output:
173 ready = False
174 if ready:
175 break
176 time.sleep( 10 )
177 utilities.assert_equals( expect=True, actual=ready,
178 onpass="ONOS summary command succeded",
179 onfail="ONOS summary command failed" )
180
181 with open( "%s/json/%s.json" % (
182 main.dependencyPath, main.cfgName) ) as cfg:
183 main.RESTs[ main.active ].setNetCfg( json.load( cfg ) )
184 with open( "%s/json/%s.chart" % (
185 main.dependencyPath, main.cfgName) ) as chart:
186 main.pingChart = json.load( chart )
187 if not ready:
188 main.log.error( "ONOS startup failed!" )
189 main.cleanup( )
190 main.exit( )
191
192 for i in range( main.numCtrls ):
193 main.CLIs[ i ].logSet( "DEBUG", "org.onosproject.segmentrouting" )
194 main.CLIs[ i ].logSet( "DEBUG", "org.onosproject.driver.pipeline" )
195 main.CLIs[ i ].logSet( "DEBUG", "org.onosproject.store.group.impl" )
196 main.CLIs[ i ].logSet( "DEBUG",
197 "org.onosproject.net.flowobjective.impl" )
198
199 @staticmethod
200 def startMininet( main, topology, args="" ):
201 main.step( "Starting Mininet Topology" )
202 arg = "--onos %d %s" % (main.numCtrls, args)
203 main.topology = topology
204 topoResult = main.Mininet1.startNet(
205 topoFile=main.Mininet1.home + main.topology, args=arg )
206 stepResult = topoResult
207 utilities.assert_equals( expect=main.TRUE,
208 actual=stepResult,
209 onpass="Successfully loaded topology",
210 onfail="Failed to load topology" )
211 # Exit if topology did not load properly
212 if not topoResult:
213 main.cleanup( )
214 main.exit( )
215
216 @staticmethod
217 def checkFlows( main, minFlowCount, dumpflows=True ):
218 main.step(
219 " Check whether the flow count is bigger than %s" % minFlowCount )
220 count = utilities.retry( main.CLIs[ main.active ].checkFlowCount,
221 main.FALSE,
222 kwargs={ 'min': minFlowCount },
223 attempts=10,
224 sleep=10 )
225 utilities.assertEquals( \
226 expect=True,
227 actual=(count > 0),
228 onpass="Flow count looks correct: " + str( count ),
229 onfail="Flow count looks wrong: " + str( count ) )
230
231 main.step( "Check whether all flow status are ADDED" )
232 flowCheck = utilities.retry( main.CLIs[ main.active ].checkFlowsState,
233 main.FALSE,
234 kwargs={ 'isPENDING': False },
235 attempts=2,
236 sleep=10 )
237 utilities.assertEquals( \
238 expect=main.TRUE,
239 actual=flowCheck,
240 onpass="Flow status is correct!",
241 onfail="Flow status is wrong!" )
242 if dumpflows:
Pier50f0bc62016-09-07 17:53:40 -0700243 main.ONOSbench.dumpONOSCmd( main.ONOSip[ main.active ],
244 "flows",
245 main.logdir,
246 "flowsBefore" + main.cfgName )
247 main.ONOSbench.dumpONOSCmd( main.ONOSip[ main.active ],
248 "groups",
249 main.logdir,
250 "groupsBefore" + main.cfgName )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700251
252 @staticmethod
253 def pingAll( main, tag="", dumpflows=True ):
254 main.log.report( "Check full connectivity" )
255 print main.pingChart
256 for entry in main.pingChart.itervalues( ):
257 print entry
258 hosts, expect = entry[ 'hosts' ], entry[ 'expect' ]
259 expect = main.TRUE if expect else main.FALSE
260 main.step( "Connectivity for %s %s" % (str( hosts ), tag) )
261 pa = main.Mininet1.pingallHosts( hosts )
262 utilities.assert_equals( expect=expect, actual=pa,
263 onpass="IP connectivity successfully tested",
264 onfail="IP connectivity failed" )
265 if dumpflows:
Pier50f0bc62016-09-07 17:53:40 -0700266 main.ONOSbench.dumpONOSCmd( main.ONOSip[ main.active ],
267 "flows",
268 main.logdir,
269 "flowsOn" + tag )
270 main.ONOSbench.dumpONOSCmd( main.ONOSip[ main.active ],
271 "groups",
272 main.logdir,
273 "groupsOn" + tag )
Jon Hall1efcb3f2016-08-23 13:42:15 -0700274
275 @staticmethod
276 def killLink( main, end1, end2, switches, links ):
277 """
278 end1,end2: identify the switches, ex.: 'leaf1', 'spine1'
279 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
280 Kill a link and verify ONOS can see the proper link change
281 """
282 main.linkSleep = float( main.params[ 'timers' ][ 'LinkDiscovery' ] )
283 main.step( "Kill link between %s and %s" % (end1, end2) )
284 LinkDown = main.Mininet1.link( END1=end1, END2=end2, OPTION="down" )
285 main.log.info(
286 "Waiting %s seconds for link down to be discovered" % main.linkSleep )
287 time.sleep( main.linkSleep )
288 topology = utilities.retry( main.CLIs[ main.active ].checkStatus,
289 main.FALSE,
290 kwargs={ 'numoswitch': switches,
291 'numolink': links },
292 attempts=10,
293 sleep=main.linkSleep )
294 result = topology & LinkDown
295 utilities.assert_equals( expect=main.TRUE, actual=result,
296 onpass="Link down successful",
297 onfail="Failed to turn off link?" )
298
299 @staticmethod
300 def restoreLink( main, end1, end2, dpid1, dpid2, port1, port2, switches,
301 links ):
302 """
303 Params:
304 end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
305 dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
306 port1, port2: respective port of the end switches that connects to the link, ex.:'1'
307 switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
308 Kill a link and verify ONOS can see the proper link change
309 """
310 main.step( "Restore link between %s and %s" % (end1, end2) )
311 result = False
312 count = 0
313 while True:
314 count += 1
315 main.Mininet1.link( END1=end1, END2=end2, OPTION="up" )
316 main.Mininet1.link( END2=end1, END1=end2, OPTION="up" )
317 main.log.info(
318 "Waiting %s seconds for link up to be discovered" % main.linkSleep )
319 time.sleep( main.linkSleep )
320 main.CLIs[ main.active ].portstate( dpid=dpid1, port=port1 )
321 main.CLIs[ main.active ].portstate( dpid=dpid2, port=port2 )
322 time.sleep( main.linkSleep )
323
324 result = main.CLIs[ main.active ].checkStatus( numoswitch=switches,
325 numolink=links )
326 if count > 5 or result:
327 break
328 utilities.assert_equals( expect=main.TRUE, actual=result,
329 onpass="Link up successful",
330 onfail="Failed to bring link up" )
331
332 @staticmethod
333 def killSwitch( main, switch, switches, links ):
334 """
335 Params: switches, links: number of expected switches and links after SwitchDown, ex.: '4', '6'
336 Completely kill a switch and verify ONOS can see the proper change
337 """
338 main.switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
339 main.step( "Kill " + switch )
340 main.log.info( "Stopping" + switch )
341 main.Mininet1.switch( SW=switch, OPTION="stop" )
342 # todo make this repeatable
343 main.log.info( "Waiting %s seconds for switch down to be discovered" % (
344 main.switchSleep) )
345 time.sleep( main.switchSleep )
346 topology = utilities.retry( main.CLIs[ main.active ].checkStatus,
347 main.FALSE,
348 kwargs={ 'numoswitch': switches,
349 'numolink': links },
350 attempts=10,
351 sleep=main.switchSleep )
352 utilities.assert_equals( expect=main.TRUE, actual=topology,
353 onpass="Kill switch successful",
354 onfail="Failed to kill switch?" )
355
356 @staticmethod
357 def recoverSwitch( main, switch, switches, links ):
358 """
359 Params: switches, links: number of expected switches and links after SwitchUp, ex.: '4', '6'
360 Recover a switch and verify ONOS can see the proper change
361 """
362 # todo make this repeatable
363 main.step( "Recovering " + switch )
364 main.log.info( "Starting" + switch )
365 main.Mininet1.switch( SW=switch, OPTION="start" )
366 main.log.info( "Waiting %s seconds for switch up to be discovered" % (
367 main.switchSleep) )
368 time.sleep( main.switchSleep )
369 topology = utilities.retry( main.CLIs[ main.active ].checkStatus,
370 main.FALSE,
371 kwargs={ 'numoswitch': switches,
372 'numolink': links },
373 attempts=10,
374 sleep=main.switchSleep )
375 utilities.assert_equals( expect=main.TRUE, actual=topology,
376 onpass="Switch recovery successful",
377 onfail="Failed to recover switch?" )
378
379 @staticmethod
380 def cleanup( main ):
381 """
382 Stop Onos-cluster.
383 Stops Mininet
384 Copies ONOS log
385 """
386 main.Mininet1.stopNet( )
387 main.ONOSbench.scp( main.ONOScli1, "/opt/onos/log/karaf.log",
388 "/tmp/karaf.log", direction="from" )
389 main.ONOSbench.cpLogsToDir( "/tmp/karaf.log", main.logdir,
390 copyFileName="karaf.log." + main.cfgName )
391 for i in range( main.numCtrls ):
392 main.ONOSbench.onosStop( main.ONOSip[ i ] )
393
394 @staticmethod
395 def killOnos( main, nodes, switches, links, expNodes ):
396 """
397 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
398 switches, links, nodes: number of expected switches, links and nodes after KillOnos, ex.: '4', '6'
399 Completely Kill an ONOS instance and verify the ONOS cluster can see the proper change
400 """
401 main.step( "Killing ONOS instance" )
402 for i in nodes:
403 killResult = main.ONOSbench.onosDie( main.CLIs[ i ].ip_address )
404 utilities.assert_equals( expect=main.TRUE, actual=killResult,
405 onpass="ONOS instance Killed",
406 onfail="Error killing ONOS instance" )
407 if i == main.active:
408 main.active = (i + 1) % main.numCtrls
409 time.sleep( 12 )
410 if len( nodes ) < main.numCtrls:
411 topology = utilities.retry( main.CLIs[ main.active ].checkStatus,
412 main.FALSE,
413 kwargs={ 'numoswitch': switches,
414 'numolink': links,
415 'numoctrl': expNodes },
416 attempts=10,
417 sleep=12 )
418 utilities.assert_equals( expect=main.TRUE, actual=topology,
419 onpass="ONOS Instance down successful",
420 onfail="Failed to turn off ONOS Instance" )
421 else:
422 main.active = -1
423
424 @staticmethod
425 def recoverOnos( main, nodes, switches, links, expNodes ):
426 """
427 Params: nodes, integer array with position of the ONOS nodes in the CLIs array
428 switches, links, nodes: number of expected switches, links and nodes after recoverOnos, ex.: '4', '6'
429 Recover an ONOS instance and verify the ONOS cluster can see the proper change
430 """
431 main.step( "Recovering ONOS instance" )
432 [ main.ONOSbench.onosStart( main.CLIs[ i ].ip_address ) for i in nodes ]
433 for i in nodes:
434 isUp = main.ONOSbench.isup( main.ONOSip[ i ] )
435 utilities.assert_equals( expect=main.TRUE, actual=isUp,
436 onpass="ONOS service is ready",
437 onfail="ONOS service did not start properly" )
438 for i in nodes:
439 main.step( "Checking if ONOS CLI is ready" )
440 main.CLIs[ i ].startCellCli( )
441 cliResult = main.CLIs[ i ].startOnosCli( main.ONOSip[ i ],
442 commandlineTimeout=60,
443 onosStartTimeout=100 )
444 utilities.assert_equals( expect=main.TRUE,
445 actual=cliResult,
446 onpass="ONOS CLI is ready",
447 onfail="ONOS CLI is not ready" )
448 main.active = i if main.active == -1 else main.active
449
450 topology = utilities.retry( main.CLIs[ main.active ].checkStatus,
451 main.FALSE,
452 kwargs={ 'numoswitch': switches,
453 'numolink': links,
454 'numoctrl': expNodes },
455 attempts=10,
456 sleep=12 )
457 utilities.assert_equals( expect=main.TRUE, actual=topology,
458 onpass="ONOS Instance down successful",
459 onfail="Failed to turn off ONOS Instance" )
460 for i in range( 10 ):
461 ready = True
462 output = main.CLIs[ main.active ].summary( )
463 if not output:
464 ready = False
465 if ready:
466 break
467 time.sleep( 10 )
468 utilities.assert_equals( expect=True, actual=ready,
469 onpass="ONOS summary command succeded",
470 onfail="ONOS summary command failed" )
471 if not ready:
472 main.log.error( "ONOS startup failed!" )
473 main.cleanup( )
474 main.exit( )
475
476 @staticmethod
477 def addHostCfg( main ):
478 """
479 Adds Host Configuration to ONOS
480 Updates expected state of the network (pingChart)
481 """
482 import json
483 hostCfg = { }
484 with open( main.dependencyPath + "/json/extra.json" ) as template:
485 hostCfg = json.load( template )
486 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'in1' ]
487 main.step( "Pushing new configuration" )
488 mac, cfg = hostCfg[ 'hosts' ].popitem( )
489 main.RESTs[ main.active ].setNetCfg( cfg[ 'basic' ],
490 subjectClass="hosts",
491 subjectKey=urllib.quote( mac,
492 safe='' ),
493 configKey="basic" )
494 main.pingChart[ 'ip' ][ 'hosts' ] += [ 'out1' ]
495 main.step( "Pushing new configuration" )
496 mac, cfg = hostCfg[ 'hosts' ].popitem( )
497 main.RESTs[ main.active ].setNetCfg( cfg[ 'basic' ],
498 subjectClass="hosts",
499 subjectKey=urllib.quote( mac,
500 safe='' ),
501 configKey="basic" )
502 main.pingChart.update( { 'vlan1': { "expect": "True",
503 "hosts": [ "olt1", "vsg1" ] } } )
504 main.pingChart[ 'vlan5' ][ 'expect' ] = 0
505 main.pingChart[ 'vlan10' ][ 'expect' ] = 0
506 ports = "[%s,%s]" % (5, 6)
507 cfg = '{"of:0000000000000001":[{"vlan":1,"ports":%s,"name":"OLT 1"}]}' % ports
508 main.RESTs[ main.active ].setNetCfg( json.loads( cfg ),
509 subjectClass="apps",
510 subjectKey="org.onosproject.segmentrouting",
511 configKey="xconnect" )
512
513 @staticmethod
514 def delHostCfg( main ):
515 """
516 Removest Host Configuration from ONOS
517 Updates expected state of the network (pingChart)
518 """
519 import json
520 hostCfg = { }
521 with open( main.dependencyPath + "/json/extra.json" ) as template:
522 hostCfg = json.load( template )
523 main.step( "Removing host configuration" )
524 main.pingChart[ 'ip' ][ 'expect' ] = 0
525 mac, cfg = hostCfg[ 'hosts' ].popitem( )
526 main.RESTs[ main.active ].removeNetCfg( subjectClass="hosts",
527 subjectKey=urllib.quote(
528 mac,
529 safe='' ),
530 configKey="basic" )
531 main.step( "Removing configuration" )
532 main.pingChart[ 'ip' ][ 'expect' ] = 0
533 mac, cfg = hostCfg[ 'hosts' ].popitem( )
534 main.RESTs[ main.active ].removeNetCfg( subjectClass="hosts",
535 subjectKey=urllib.quote(
536 mac,
537 safe='' ),
538 configKey="basic" )
539 main.step( "Removing vlan configuration" )
540 main.pingChart[ 'vlan1' ][ 'expect' ] = 0
541 main.RESTs[ main.active ].removeNetCfg( subjectClass="apps",
542 subjectKey="org.onosproject.segmentrouting",
543 configKey="xconnect" )