blob: 43f80ebd7fa60cb301f358e9e71f6c79c89cdb85 [file] [log] [blame]
kelvin-onlab1d381fe2015-07-14 16:24:56 -07001"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07002Copyright 2015 Open Networking Foundation (ONF)
3
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
21
22"""
kelvin-onlab1d381fe2015-07-14 16:24:56 -070023 Wrapper function for FuncTopo
24 Includes onosclidriver and mininetclidriver functions
25"""
26import time
27import json
28import re
29
30def __init__( self ):
31 self.default = ''
32
Chiyu Chengb8c2c842016-10-05 12:40:49 -070033def getTimestampFromString( main, targetString ):
34 #Get time string from the target string
35 try:
36 assert type( targetString ) is str
37 timeString = targetString.split( ' | ' )
38 timeString = timeString[ 0 ]
39 from datetime import datetime
40 # convert time string to timestamp
41 t = datetime.strptime( timeString, "%Y-%m-%d %H:%M:%S,%f" )
42 import time
43 timestamp = time.mktime( t.timetuple() )
44 timestamp += int( t.microsecond / 1000 ) / 1000.0
45 return timestamp
46 except AssertionError:
47 main.log.error( "Got nothing firom log" )
48 return -1
49 except IndexError:
50 main.log.error( "Time string index error" )
51 return -1
52 except ValueError:
53 main.log.error( "Got wrong string from log" )
54 return -1
55
Chiyu Cheng899621b2016-11-14 11:14:48 -080056def getRoleRequestTimeFromTshark( main ):
57 try:
58 main.log.info( "Get role request time" )
59 with open(main.tsharkResultPath, "r" ) as resultFile:
60 resultText = resultFile.readlines()
61 # select the last role request string
62 roleRequestString = resultText[ len( resultText ) - 1 ]
63 main.log.info( roleRequestString )
64 # get timestamp from role request string
65 roleRequestTime = roleRequestString.split( " " )
66 resultFile.close()
67 return float(roleRequestTime[1])
68 except IndexError:
69 main.log.error("Got wrong role request string from Tshark file")
70 return -1
71
72def compareTimeDiffWithRoleRequest(main, term, Mode, index=0 ):
73 '''
74 Description:
75 Compare the time difference between the time of target term and the time of role request
76 Inclides onosclidriver functions
77
78 '''
79 try:
You Wang118ba582017-01-02 17:14:43 -080080 termInfo = main.CLIs[ index ].logSearch( mode=Mode, searchTerm=term )
Chiyu Cheng899621b2016-11-14 11:14:48 -080081 termTime = getTimestampFromString( main, termInfo[ 0 ] )
82 roleRequestTime = getRoleRequestTimeFromTshark( main )
83 if termTime == -1 or roleRequestTime == -1:
84 main.writeData = -1
85 main.log.error( "Can't compare the difference with role request time" )
86 return -1
Jon Hall465d56c2016-12-05 10:03:02 -080087 # Only concern about the absolute value of difference.
Chiyu Cheng899621b2016-11-14 11:14:48 -080088 return abs( roleRequestTime - termTime )
89 except IndexError:
90 main.log.error( "Catch the wrong information of search term " )
91 main.writeData = -1
92 return -1
93
Chiyu Chengb8c2c842016-10-05 12:40:49 -070094def getInfoFromLog( main, term1, mode1, term2, mode2, index=0, funcMode='TD' ):
95 '''
96 Description:
97 Get needed informations of the search term from karaf.log
98 Includes onosclidriver functions
99 Function mode:
100 TD (time difference):
101 Get time difference between start and end
102 Term1: startTerm
103 Term2: endTerm
104 DR (disconnect rate):
105 Get switch disconnect rate
106 Term1: disconnectTerm
107 Term2: connectTerm
108
109 '''
110 try:
You Wang118ba582017-01-02 17:14:43 -0800111 termInfo1 = main.CLIs[ index ].logSearch( mode=mode1, searchTerm=term1 )
112 termInfo2 = main.CLIs[ index ].logSearch( mode=mode2, searchTerm=term2 )
Chiyu Chengb8c2c842016-10-05 12:40:49 -0700113 if funcMode == 'TD':
114 startTime = getTimestampFromString( main, termInfo1[0] )
115 endTime = getTimestampFromString ( main, termInfo2[0] )
116 if startTime == -1 or endTime == -1:
117 main.log.error( "Wrong Time!" )
118 main.writeData = -1
119 return -1
120 return endTime - startTime
121 if funcMode == 'DR':
122 #In this mode, termInfo1 means the total number of switch disconnection and
123 #termInfo2 means the total number of new switch connection
124 #termInfo2 - termInfo1 means the actual real number of switch connection.
125 disconnection = int( termInfo1 ) * 1.0
126 expectConnection = int( main.currScale ) ** 2
127 realConnection = int( termInfo2 ) - int( termInfo1 )
128 if expectConnection != realConnection:
129 main.log.error( "The number of real switch connection doesn't match the number of expected connection" )
130 main.writeData = -1
131 return -1
132 rate = disconnection / expectConnection
133 return rate
134 except IndexError:
135 main.log.error( "Catch the wrong information of search term" )
136 main.writeData = -1
137 return -1
138
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700139def testTopology( main, topoFile='', args='', mnCmd='', timeout=300, clean=True ):
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700140 """
141 Description:
142 This function combines different wrapper functions in this module
143 to simulate a topology test
144 Test Steps:
145 - Load topology
146 - Discover topology
147 - Compare topology
148 - pingall
149 - Bring links down
150 - Compare topology
151 - pingall
152 - Bring links up
153 - Compare topology
154 - pingall
155 Options:
156 clean: Does sudo mn -c to clean mininet residue
157 Please read mininetclidriver.py >> startNet( .. ) function for details
158 Returns:
159 Returns main.TRUE if the test is successful, main.FALSE otherwise
160 """
161 testTopoResult = main.TRUE
162 compareTopoResult = main.TRUE
163 topoObjectResult = main.TRUE
164 stopResult = main.TRUE
165
166 if clean:
167 # Cleans minient
168 stopResult = stopMininet( main )
169
170 # Restart ONOS to clear hosts test new mininet topology
171 reinstallOnosResult = reinstallOnos( main )
172
173 # Starts topology
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700174 startResult = startNewTopology( main, topoFile, args, mnCmd, timeout=timeout )
GlennRC1c5df3c2015-08-27 16:12:09 -0700175 # onos needs time to see the links
176 time.sleep(15)
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700177
178 # Gets list of switches in mininet
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700179 #assignSwitch( main )
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700180
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700181 testTopoResult = startResult and topoObjectResult
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700182
183
184 return testTopoResult
185
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700186def startNewTopology( main, topoFile='', args='', mnCmd='', timeout=900 ):
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700187 """
188 Description:
189 This wrapper function starts new topology
190 Options:
191 Please read mininetclidriver.py >> startNet( .. ) function for details
192 Return:
193 Returns main.TRUE if topology is successfully created by mininet,
194 main.FALSE otherwise
195 NOTE:
196 Assumes Mininet1 is the name of the handler
197 """
198 assert main, "There is no main variable"
199 assert main.Mininet1, "Mininet 1 is not created"
200 result = main.TRUE
201
202 main.log.info( main.topoName + ": Starting new Mininet topology" )
203
204 # log which method is being used
205 if topoFile:
206 main.log.info( main.topoName + ": Starting topology with " +
207 topoFile + "topology file" )
208 elif not topoFile and not mnCmd:
209 main.log.info( main.topoName + ": Starting topology using" +
210 " the topo file" )
211 elif topoFile and mnCmd:
212 main.log.error( main.topoName + ": You can only use one " +
213 "method to start a topology" )
214 elif mnCmd:
215 main.log.info( main.topoName + ": Starting topology with '" +
216 mnCmd + "' Mininet command" )
217
218
219 result = main.Mininet1.startNet( topoFile=topoFile,
220 args=args,
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700221 mnCmd=mnCmd,
222 timeout=timeout)
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700223
224 return result
225
226def stopMininet( main ):
227 """
228 Stops current topology and execute mn -c basically triggers
229 stopNet in mininetclidrivers
230
231 NOTE: Mininet should be running when issuing this command other wise
232 the this function will cause the test to stop
233 """
234 stopResult = main.TRUE
235 stopResult = main.Mininet1.stopNet()
236 time.sleep( 30 )
237 if not stopResult:
238 main.log.info( main.topoName + ": Did not stop Mininet topology" )
239 return stopResult
240
241def compareTopo( main ):
242 """
243 Compare topology( devices, links, ports, hosts ) between ONOS and
244 mininet using sts
245 """
246 devices = []
247 links = []
248 ports = []
249 hosts = []
250 switchResult = []
251 linksResult = []
252 portsResult = []
253 hostsResult = []
254 mnSwitches = main.Mininet1.getSwitches()
255 mnLinks = main.Mininet1.getLinks()
256 mnHosts = main.Mininet1.getHosts()
257 compareTopoResult = main.TRUE
258
259 for i in range( main.numCtrls ):
260 devices.append( json.loads( main.CLIs[ i ].devices() ) )
261 links.append( json.loads( main.CLIs[ i ].links() ) )
262 ports.append( json.loads( main.CLIs[ i ].ports() ) )
263 hosts.append( json.loads( main.CLIs[ i ].hosts() ) )
264
265 # Comparing switches
266 main.log.info( main.topoName + ": Comparing switches in each ONOS nodes" +
267 " with Mininet" )
268 for i in range( main.numCtrls ):
269 tempResult = main.Mininet1.compareSwitches( mnSwitches,
270 devices[ i ],
271 ports[ i ] )
272 switchResult.append( tempResult )
273 if tempResult == main.FALSE:
274 main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
275 " switch view is incorrect " )
276
277 if all( result == main.TRUE for result in switchResult ):
278 main.log.info( main.topoName + ": Switch view in all ONOS nodes "+
279 "are correct " )
280 else:
281 compareTopoResult = main.FALSE
282
283 # Comparing links
284 main.log.info( main.topoName + ": Comparing links in each ONOS nodes" +
285 " with Mininet" )
286 for i in range( main.numCtrls ):
287 tempResult = main.Mininet1.compareLinks( mnSwitches,
288 mnLinks,
289 links[ i ] )
290 linksResult.append( tempResult )
291 if tempResult == main.FALSE:
292 main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
293 " links view are incorrect " )
294
295 if all( result == main.TRUE for result in linksResult ):
296 main.log.info( main.topoName + ": Links view in all ONOS nodes "+
297 "are correct " )
298 else:
299 compareTopoResult = main.FALSE
300
301 # Comparing hosts
302 main.log.info( main.topoName + ": Comparing hosts in each ONOS nodes" +
303 " with Mininet" )
304 for i in range( main.numCtrls ):
305 tempResult = main.Mininet1.compareHosts( mnHosts, hosts[ i ] )
306 hostsResult.append( tempResult )
307 if tempResult == main.FALSE:
308 main.log.error( main.topoName + ": ONOS-" + str( i + 1 ) +
309 " hosts view are incorrect " )
310
311 if all( result == main.TRUE for result in hostsResult ):
312 main.log.info( main.topoName + ": Hosts view in all ONOS nodes "+
313 "are correct " )
314 else:
315 compareTopoResult = main.FALSE
316
317 return compareTopoResult
318
319def assignSwitch( main ):
320 """
321 Returns switch list using getSwitch in Mininet driver
322 """
323 switchList = []
324 assignResult = main.TRUE
325 switchList = main.Mininet1.getSwitch()
326 assignResult = main.Mininet1.assignSwController( sw=switchList,
327 ip=main.ONOSip[ 0 ],
GlennRC632e2892015-10-19 18:58:41 -0700328 port=6633 )
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700329
330 for sw in switchList:
331 response = main.Mininet1.getSwController( sw )
332 if re.search( "tcp:" + main.ONOSip[ 0 ], response ):
333 assignResult = assignResult and main.TRUE
334 else:
335 assignResult = main.FALSE
336
337 return switchList
338
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700339def connectivity( main, timeout=900, shortCircuit=True, acceptableFailed=20 ):
340 """
341 Use fwd app and pingall to discover all the hosts
342 """
343 activateResult = main.TRUE
344 appCheck = main.TRUE
345 getDataResult = main.TRUE
346 main.log.info( main.topoName + ": Activating reactive forwarding app " )
347 activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
348
349 if main.hostsData:
350 main.hostsData = {}
351 for i in range( main.numCtrls ):
352 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
353 if appCheck != main.TRUE:
354 main.log.warn( main.CLIs[ i ].apps() )
355 main.log.warn( main.CLIs[ i ].appIDs() )
356
357 time.sleep( main.fwdSleep )
358
359 # Discover hosts using pingall
360 pingResult = main.Mininet1.pingall( timeout=timeout,
361 shortCircuit=shortCircuit,
362 acceptableFailed=acceptableFailed )
363
364 main.log.info( main.topoName + ": Deactivate reactive forwarding app " )
365 activateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
366 for i in range( main.numCtrls ):
367 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
368 if appCheck != main.TRUE:
369 main.log.warn( main.CLIs[ i ].apps() )
370 main.log.warn( main.CLIs[ i ].appIDs() )
371
372 return pingResult
373
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700374def getHostsData( main ):
375 """
376 Use fwd app and pingall to discover all the hosts
377 """
378 activateResult = main.TRUE
379 appCheck = main.TRUE
380 getDataResult = main.TRUE
381 main.log.info( main.topoName + ": Activating reactive forwarding app " )
382 activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
383
384 if main.hostsData:
385 main.hostsData = {}
386 for i in range( main.numCtrls ):
387 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
388 if appCheck != main.TRUE:
389 main.log.warn( main.CLIs[ i ].apps() )
390 main.log.warn( main.CLIs[ i ].appIDs() )
391
392 time.sleep( main.fwdSleep )
393 # Discover hosts using pingall
394 pingResult = main.Mininet1.pingall( timeout=900 )
395
396 hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
397 hosts = main.Mininet1.getHosts().keys()
398
399 for host in hosts:
400 main.hostsData[ host ] = {}
401 main.hostsData[ host ][ 'mac' ] = \
402 main.Mininet1.getMacAddress( host ).upper()
403 for hostj in hostsJson:
404 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
405 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
406 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
407 main.hostsData[ host ][ 'location' ] = \
Jeremy Ronquillo0e538bc2017-06-13 15:16:09 -0700408 hostj[ 'locations' ][ 0 ][ 'elementId' ] + '/' + \
409 hostj[ 'locations' ][ 0 ][ 'port' ]
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700410 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
411
412 if activateResult and main.hostsData:
413 main.log.info( main.topoName + ": Successfully used fwd app" +
414 " to discover hosts " )
415 getDataResult = main.TRUE
416 else:
417 main.log.info( main.topoName + ": Failed to use fwd app" +
418 " to discover hosts " )
419 getDataResult = main.FALSE
420
421 main.log.info( main.topoName + ": Deactivate reactive forwarding app " )
422 activateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
423 for i in range( main.numCtrls ):
424 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
425 if appCheck != main.TRUE:
426 main.log.warn( main.CLIs[ i ].apps() )
427 main.log.warn( main.CLIs[ i ].appIDs() )
428
429 # This data can be use later for intents
430 print main.hostsData
431
432 return getDataResult
433
434def reinstallOnos( main ):
435 """
436 Description:
437 Stop and start ONOS that clears hosts,devices etc. in order to test
438 new mininet topology
439 Return:
440 Retruns main.TRUE for a successful restart, main.FALSE otherwise.
441 """
442 uninstallResult = []
443 installResult = []
444 stopResult = []
445 startResult = []
446 onosIsUpResult = []
447 restartResult = main.TRUE
448
449 main.log.info( main.topoName + ": Uninstall ONOS cluster" )
450 for ip in main.ONOSip:
451 uninstallResult.append( main.ONOSbench.onosUninstall( nodeIp=ip ) )
452
453 if all( result == main.TRUE for result in uninstallResult ):
454 main.log.info( main.topoName + ": Successfully uninstall ONOS cluster" )
455 else:
456 restartResult = main.FALSE
457 main.log.error( main.topoName + ": Failed to uninstall ONOS cluster" )
458
459 time.sleep( main.startUpSleep )
460
461 main.log.info( main.topoName + ": Installing ONOS cluster" )
462
463 for i in range( main.numCtrls ):
464 installResult.append( main.ONOSbench.onosInstall(
465 node=main.ONOSip[ i ] ) )
466
467 if all( result == main.TRUE for result in installResult ):
468 main.log.info( main.topoName + ": Successfully installed ONOS cluster" )
469 else:
470 restartResult = main.FALSE
471 main.log.error( main.topoName + ": Failed to install ONOS cluster" )
472
You Wangf5de25b2017-01-06 15:13:01 -0800473 main.log.info( main.topoName + ": set up ONOS secure SSH" )
474 secureSshResult = []
475 for i in range( int( main.numCtrls ) ):
476 secureSshResult.append( main.onosSecureSSH( node=main.ONOSip[i] ) )
477 if all( result == main.TRUE for result in secureSshResult ):
478 main.log.info( main.topoName + ": Successfully set up ONOS secure SSH" )
479 else:
480 main.log.error( main.topoName + ": Failed to set up ONOS secure SSH" )
481 restartResult = main.FALSE
482
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700483 for i in range( main.numCtrls ):
484 onosIsUpResult.append( main.ONOSbench.isup( main.ONOSip[ i ] ) )
485
486 if all( result == main.TRUE for result in onosIsUpResult ):
487 main.log.report( "ONOS instance is up and ready" )
488 else:
489 main.log.report( "ONOS instance may not be up, stop and " +
490 "start ONOS again " )
491 for i in range( main.numCtrls ):
492 stopResult.append( main.ONOSbench.onosStop( main.ONOSip[ i ] ) )
493
494 if all( result == main.TRUE for result in stopResult ):
495 main.log.info( main.topoName + ": Successfully stop ONOS cluster" )
496 else:
497 main.log.error( main.topoName + ": Failed to stop ONOS cluster" )
498
499 for i in range( main.numCtrls ):
500 startResult.append( main.ONOSbench.onosStart( main.ONOSip[ i ] ) )
501
502 if all( result == main.TRUE for result in startResult ):
503 main.log.info( main.topoName + ": Successfully start ONOS cluster" )
504 else:
505 main.log.error( main.topoName + ": Failed to start ONOS cluster" )
506
kelvin-onlab1d381fe2015-07-14 16:24:56 -0700507 main.log.info( main.topoName + ": Starting ONOS CLI" )
508 cliResult = []
509 for i in range( main.numCtrls ):
510 cliResult.append( main.CLIs[ i ].startOnosCli( main.ONOSip[ i ] ) )
511
512 if all( result == main.TRUE for result in cliResult ):
513 main.log.info( main.topoName + ": Successfully start ONOS cli" )
514 else:
515 main.log.error( main.topoName + ": Failed to start ONOS cli" )
516 restartResult = main.FALSE
517
518
519 return restartResult
520
521
522