YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 1 | """ |
| 2 | SCPFhostLat |
| 3 | This test will test the host found latency. |
| 4 | Host will arping a ip address, tshark will caputure the package time, then compare with the topology event timestamp. |
| 5 | Test will run with 1 node from start, and scale up to 7 nodes. |
| 6 | The event timestamp will only greb the latest one, then calculate average and standar dev. |
| 7 | |
| 8 | yunpeng@onlab.us |
| 9 | """ |
| 10 | class SCPFhostLat: |
| 11 | |
| 12 | def __init__( self ): |
| 13 | self.default = '' |
| 14 | |
| 15 | def CASE0( self, main): |
| 16 | import sys |
| 17 | import json |
| 18 | import time |
| 19 | import os |
| 20 | import imp |
| 21 | |
| 22 | main.case( "Constructing test variables and building ONOS package" ) |
| 23 | main.step( "Constructing test variables" ) |
| 24 | stepResult = main.FALSE |
| 25 | |
| 26 | # Test variables |
| 27 | main.testOnDirectory = os.path.dirname( os.getcwd ( ) ) |
| 28 | main.cellName = main.params[ 'ENV' ][ 'cellName' ] |
| 29 | main.apps = main.params[ 'ENV' ][ 'cellApps' ] |
| 30 | main.scale = ( main.params[ 'SCALE' ] ).split( "," ) |
| 31 | main.ONOSport = main.params[ 'CTRL' ][ 'port' ] |
| 32 | main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] ) |
| 33 | main.installSleep = int( main.params[ 'SLEEP' ][ 'install' ] ) |
| 34 | main.measurementSleep = int( main.params['SLEEP']['measurement']) |
| 35 | main.timeout = int( main.params['SLEEP']['timeout'] ) |
| 36 | main.dbFileName = main.params['DATABASE']['file'] |
| 37 | main.cellData = {} # for creating cell file |
| 38 | |
| 39 | # Tshark params |
| 40 | main.tsharkResultPath = main.params['TSHARK']['tsharkPath'] |
| 41 | main.tsharkPacketIn = main.params['TSHARK']['tsharkPacketIn'] |
| 42 | |
| 43 | main.numlter = main.params['TEST']['numIter'] |
| 44 | main.iterIgnore = int(main.params['TEST']['iterIgnore']) |
| 45 | main.hostTimestampKey = main.params['TEST']['hostTimestamp'] |
| 46 | main.thresholdStr = main.params['TEST']['singleSwThreshold'] |
| 47 | main.thresholdObj = main.thresholdStr.split(',') |
| 48 | main.thresholdMin = int(main.thresholdObj[0]) |
| 49 | main.thresholdMax = int(main.thresholdObj[1]) |
| 50 | main.threadID = 0 |
| 51 | |
| 52 | main.CLIs = [] |
| 53 | main.ONOSip = [] |
| 54 | main.maxNumBatch = 0 |
| 55 | main.ONOSip = main.ONOSbench.getOnosIps() |
| 56 | main.log.info(main.ONOSip) |
| 57 | main.setupSkipped = False |
| 58 | |
| 59 | gitBranch = main.params[ 'GIT' ][ 'branch' ] |
| 60 | gitPull = main.params[ 'GIT' ][ 'pull' ] |
| 61 | nic = main.params['DATABASE']['nic'] |
| 62 | node = main.params['DATABASE']['node'] |
| 63 | nic = main.params['DATABASE']['nic'] |
| 64 | node = main.params['DATABASE']['node'] |
| 65 | stepResult = main.TRUE |
| 66 | |
| 67 | main.log.info("Cresting DB file") |
| 68 | with open(main.dbFileName, "w+") as dbFile: |
| 69 | dbFile.write("") |
| 70 | |
| 71 | utilities.assert_equals( expect=main.TRUE, |
| 72 | actual=stepResult, |
| 73 | onpass="environment set up successfull", |
| 74 | onfail="environment set up Failed" ) |
| 75 | |
| 76 | def CASE1( self ): |
| 77 | # main.scale[ 0 ] determines the current number of ONOS controller |
| 78 | main.CLIs = [] |
| 79 | main.numCtrls = int( main.scale[ 0 ] ) |
| 80 | main.log.info( "Creating list of ONOS cli handles" ) |
| 81 | for i in range(main.numCtrls): |
| 82 | main.CLIs.append( getattr( main, 'ONOScli%s' % (i+1) ) ) |
| 83 | |
| 84 | main.log.info(main.CLIs) |
| 85 | if not main.CLIs: |
| 86 | main.log.error( "Failed to create the list of ONOS cli handles" ) |
| 87 | main.cleanup() |
| 88 | main.exit() |
| 89 | |
| 90 | main.commit = main.ONOSbench.getVersion(report=True) |
| 91 | main.commit = main.commit.split(" ")[1] |
| 92 | |
| 93 | if gitPull == 'True': |
| 94 | if not main.startUp.onosBuild( main, gitBranch ): |
| 95 | main.log.error( "Failed to build ONOS" ) |
| 96 | main.cleanup() |
| 97 | main.exit() |
| 98 | else: |
| 99 | main.log.warn( "Did not pull new code so skipping mvn " + |
| 100 | "clean install" ) |
| 101 | with open(main.dbFileName, "a") as dbFile: |
| 102 | temp = "'" + main.commit + "'," |
| 103 | temp += "'" + nic + "'," |
| 104 | dbFile.write(temp) |
| 105 | dbFile.close() |
| 106 | |
| 107 | def CASE2( self, main ): |
| 108 | """ |
| 109 | - Uninstall ONOS cluster |
| 110 | - Verify ONOS start up |
| 111 | - Install ONOS cluster |
| 112 | - Connect to cli |
| 113 | """ |
| 114 | main.log.info( "Starting up %s node(s) ONOS cluster" % main.numCtrls) |
| 115 | main.log.info( "Safety check, killing all ONOS processes" + |
| 116 | " before initiating environment setup" ) |
| 117 | |
| 118 | for i in range( main.numCtrls ): |
You Wang | b98a9fa | 2017-02-15 17:27:42 -0800 | [diff] [blame^] | 119 | main.ONOSbench.onosStop( main.ONOSip[ i ] ) |
| 120 | main.ONOSbench.onosKill( main.ONOSip[ i ] ) |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 121 | |
| 122 | main.log.info( "NODE COUNT = %s" % main.numCtrls) |
| 123 | |
| 124 | tempOnosIp = [] |
| 125 | for i in range( main.numCtrls ): |
| 126 | tempOnosIp.append( main.ONOSip[i] ) |
| 127 | |
| 128 | main.ONOSbench.createCellFile( main.ONOSbench.ip_address, |
| 129 | "temp", |
| 130 | main.Mininet1.ip_address, |
| 131 | main.apps, |
| 132 | tempOnosIp ) |
| 133 | |
| 134 | main.step( "Apply cell to environment" ) |
| 135 | cellResult = main.ONOSbench.setCell( "temp" ) |
| 136 | verifyResult = main.ONOSbench.verifyCell() |
| 137 | stepResult = cellResult and verifyResult |
| 138 | utilities.assert_equals( expect=main.TRUE, |
| 139 | actual=stepResult, |
| 140 | onpass="Successfully applied cell to " + \ |
| 141 | "environment", |
| 142 | onfail="Failed to apply cell to environment " ) |
| 143 | |
| 144 | main.step( "Creating ONOS package" ) |
Jon Hall | bd60ea0 | 2016-08-23 10:03:59 -0700 | [diff] [blame] | 145 | packageResult = main.ONOSbench.buckBuild() |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 146 | stepResult = packageResult |
| 147 | utilities.assert_equals( expect=main.TRUE, |
| 148 | actual=stepResult, |
| 149 | onpass="Successfully created ONOS package", |
| 150 | onfail="Failed to create ONOS package" ) |
| 151 | |
| 152 | main.step( "Uninstall ONOS package on all Nodes" ) |
| 153 | uninstallResult = main.TRUE |
| 154 | for i in range( int( main.numCtrls ) ): |
| 155 | main.log.info( "Uninstalling package on ONOS Node IP: " + main.ONOSip[i] ) |
| 156 | u_result = main.ONOSbench.onosUninstall( main.ONOSip[i] ) |
| 157 | utilities.assert_equals( expect=main.TRUE, actual=u_result, |
| 158 | onpass="Test step PASS", |
| 159 | onfail="Test step FAIL" ) |
| 160 | uninstallResult = ( uninstallResult and u_result ) |
| 161 | |
| 162 | main.step( "Install ONOS package on all Nodes" ) |
| 163 | installResult = main.TRUE |
| 164 | for i in range( int( main.numCtrls ) ): |
| 165 | main.log.info( "Installing package on ONOS Node IP: " + main.ONOSip[i] ) |
| 166 | i_result = main.ONOSbench.onosInstall( node=main.ONOSip[i] ) |
| 167 | utilities.assert_equals( expect=main.TRUE, actual=i_result, |
| 168 | onpass="Test step PASS", |
| 169 | onfail="Test step FAIL" ) |
| 170 | installResult = installResult and i_result |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 171 | |
Chiyu Cheng | ef10950 | 2016-11-21 15:51:38 -0800 | [diff] [blame] | 172 | main.step( "Set up ONOS secure SSH" ) |
| 173 | secureSshResult = main.TRUE |
| 174 | for i in range( int( main.numCtrls ) ): |
| 175 | secureSshResult = secureSshResult and main.ONOSbench.onosSecureSSH( node=main.ONOSip[i] ) |
| 176 | utilities.assert_equals( expect=main.TRUE, actual=secureSshResult, |
| 177 | onpass="Test step PASS", |
| 178 | onfail="Test step FAIL" ) |
| 179 | |
You Wang | 0357c43 | 2017-01-09 16:13:33 -0800 | [diff] [blame] | 180 | time.sleep( main.startUpSleep ) |
| 181 | main.step( "Starting ONOS service" ) |
| 182 | stopResult = main.TRUE |
| 183 | startResult = main.TRUE |
| 184 | onosIsUp = main.TRUE |
| 185 | |
| 186 | for i in range( main.numCtrls ): |
| 187 | onosIsUp = onosIsUp and main.ONOSbench.isup( main.ONOSip[ i ] ) |
| 188 | if onosIsUp == main.TRUE: |
| 189 | main.log.report( "ONOS instance is up and ready" ) |
| 190 | else: |
| 191 | main.log.report( "ONOS instance may not be up, stop and " + |
| 192 | "start ONOS again " ) |
| 193 | for i in range( main.numCtrls ): |
| 194 | stopResult = stopResult and \ |
| 195 | main.ONOSbench.onosStop( main.ONOSip[ i ] ) |
| 196 | for i in range( main.numCtrls ): |
| 197 | startResult = startResult and \ |
| 198 | main.ONOSbench.onosStart( main.ONOSip[ i ] ) |
| 199 | stepResult = onosIsUp and stopResult and startResult |
| 200 | utilities.assert_equals( expect=main.TRUE, |
| 201 | actual=stepResult, |
| 202 | onpass="ONOS service is ready", |
| 203 | onfail="ONOS service did not start properly" ) |
| 204 | |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 205 | main.step( "Start ONOS CLI on all nodes" ) |
| 206 | cliResult = main.TRUE |
Jon Hall | 6509dbf | 2016-06-21 17:01:17 -0700 | [diff] [blame] | 207 | main.step(" Start ONOS cli using thread ") |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 208 | time.sleep( main.startUpSleep ) |
| 209 | startCliResult = main.TRUE |
| 210 | pool = [] |
| 211 | |
| 212 | for i in range( int( main.numCtrls) ): |
| 213 | t = main.Thread( target=main.CLIs[i].startOnosCli, |
| 214 | threadID=main.threadID, |
| 215 | name="startOnosCli", |
| 216 | args=[ main.ONOSip[i] ], |
| 217 | kwargs = {"onosStartTimeout":main.timeout} ) |
| 218 | pool.append(t) |
| 219 | t.start() |
| 220 | main.threadID = main.threadID + 1 |
| 221 | for t in pool: |
| 222 | t.join() |
| 223 | startCliResult = startCliResult and t.result |
| 224 | time.sleep( main.startUpSleep ) |
| 225 | |
| 226 | def CASE11( self, main ): |
| 227 | main.log.info( "set and configure Application" ) |
| 228 | import json |
| 229 | import time |
| 230 | time.sleep(main.startUpSleep) |
| 231 | main.step( "Activating org.onosproject.proxyarp" ) |
| 232 | appStatus = utilities.retry( main.ONOSrest1.activateApp, |
| 233 | main.FALSE, |
| 234 | ['org.onosproject.proxyarp'], |
| 235 | sleep=3, |
| 236 | attempts=3 ) |
| 237 | utilities.assert_equals( expect=main.TRUE, |
| 238 | actual=appStatus, |
| 239 | onpass="Successfully activated proxyarp", |
| 240 | onfail="Failed to activated proxyarp") |
| 241 | |
| 242 | main.step( "Set up Default Topology Provider" ) |
| 243 | appStatus = main.TRUE |
| 244 | configName = 'org.onosproject.net.topology.impl.DefaultTopologyProvider' |
| 245 | configParam = 'maxEvents' |
| 246 | appStatus = appStatus and main.CLIs[0].setCfg( configName, configParam,'1' ) |
| 247 | configParam = 'maxBatchMs' |
| 248 | appStatus = appStatus and main.CLIs[0].setCfg( configName, configParam, '0') |
| 249 | configParam = 'maxIdleMs' |
| 250 | appStatus = appStatus and main.CLIs[0].setCfg( configName, configParam,'0' ) |
| 251 | utilities.assert_equals( expect=main.TRUE, |
| 252 | actual=appStatus, |
| 253 | onpass="Successfully set DefaultTopologyProvider", |
| 254 | onfail="Failed to set DefaultTopologyProvider" ) |
| 255 | |
| 256 | time.sleep(main.startUpSleep) |
| 257 | main.step('Starting mininet topology') |
| 258 | mnStatus = main.Mininet1.startNet(args='--topo=linear,1') |
| 259 | utilities.assert_equals( expect=main.TRUE, |
| 260 | actual=mnStatus, |
| 261 | onpass="Successfully started Mininet", |
| 262 | onfail="Failed to activate Mininet" ) |
| 263 | main.step("Assinging masters to switches") |
| 264 | switches = main.Mininet1.getSwitches() |
| 265 | swStatus = main.Mininet1.assignSwController( sw=switches.keys(), ip=main.ONOSip[0] ) |
| 266 | utilities.assert_equals( expect=main.TRUE, |
| 267 | actual=swStatus, |
| 268 | onpass="Successfully assigned switches to masters", |
| 269 | onfail="Failed assign switches to masters" ) |
| 270 | |
| 271 | time.sleep(main.startUpSleep) |
| 272 | |
| 273 | def CASE20(self, main): |
| 274 | """ |
| 275 | host1 send arping package and measure latency |
| 276 | |
| 277 | There are only 1 levels of latency measurements to this test: |
| 278 | 1 ) ARPING-to-device measurement: Measurement the time from host1 |
| 279 | send apring package to onos processing the host event |
| 280 | |
| 281 | """ |
| 282 | import time |
| 283 | import subprocess |
| 284 | import json |
| 285 | import requests |
| 286 | import os |
| 287 | import numpy |
| 288 | |
| 289 | # Host adding measurement |
| 290 | assertion = main.TRUE |
| 291 | |
| 292 | main.log.report('Latency of adding one host to ONOS') |
| 293 | main.log.report('First ' + str(main.iterIgnore) + ' iterations ignored' + ' for jvm warmup time') |
| 294 | main.log.report('Total iterations of test: ' + str(main.numlter)) |
| 295 | |
| 296 | addingHostTime = [] |
| 297 | metricsResultList = [] |
| 298 | for i in range(0, int(main.numlter)): |
| 299 | main.log.info('Clean up data file') |
| 300 | with open(main.tsharkResultPath, "w") as dbFile: |
| 301 | dbFile.write("") |
| 302 | |
| 303 | main.log.info('Starting tshark capture') |
| 304 | main.ONOSbench.tsharkGrep(main.tsharkPacketIn, main.tsharkResultPath) |
| 305 | time.sleep(main.measurementSleep) |
| 306 | |
| 307 | main.log.info('host 1 arping...') |
| 308 | main.Mininet1.arping(srcHost='h1', dstHost='10.0.0.2') |
| 309 | |
| 310 | time.sleep(main.measurementSleep) |
| 311 | |
| 312 | main.log.info('Stopping all Tshark processes') |
| 313 | main.ONOSbench.tsharkStop() |
| 314 | |
| 315 | time.sleep(main.measurementSleep) |
| 316 | |
| 317 | # Get tshark output |
| 318 | with open(main.tsharkResultPath, "r") as resultFile: |
| 319 | resultText = resultFile.readline() |
| 320 | main.log.info('Capture result:' + resultText) |
| 321 | resultText = resultText.split(' ') |
| 322 | if len(resultText) > 1: |
| 323 | tsharkResultTime = float(resultText[1]) * 1000.0 |
| 324 | else: |
| 325 | main.log.error('Tshark output file for packet_in' + ' returned unexpected results') |
| 326 | hostTime = 0 |
| 327 | caseResult = main.FALSE |
| 328 | resultFile.close() |
| 329 | # Compare the timestemps, and get the lowest one. |
| 330 | temp = 0; |
| 331 | # Get host event timestamps from each nodes |
| 332 | for node in range (0, main.numCtrls): |
| 333 | metricsResult = json.loads(main.CLIs[node].topologyEventsMetrics()) |
| 334 | metricsResult = metricsResult.get(main.hostTimestampKey).get("value") |
| 335 | main.log.info("ONOS topology event matrics timestemp: {}".format(str(metricsResult)) ) |
| 336 | |
| 337 | if temp < metricsResult: |
| 338 | temp = metricsResult |
| 339 | metricsResult = temp |
| 340 | |
| 341 | addingHostTime.append(float(metricsResult) - tsharkResultTime) |
| 342 | main.log.info("Result of this iteration: {}".format( str( float(metricsResult) - tsharkResultTime) )) |
| 343 | # gethost to remove |
| 344 | gethost = main.ONOSrest1.hosts() |
| 345 | HosttoRemove = [] |
| 346 | HosttoRemove.append( json.loads( gethost[1:len(gethost)-1] ).get('id') ) |
| 347 | main.CLIs[0].removeHost(HosttoRemove) |
| 348 | |
YPZhang | 82ca589 | 2016-03-01 15:32:09 -0800 | [diff] [blame] | 349 | main.log.info("Result List: {}".format(addingHostTime)) |
| 350 | |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 351 | # calculate average latency from each nodes |
| 352 | averageResult = numpy.average(addingHostTime) |
YPZhang | 82ca589 | 2016-03-01 15:32:09 -0800 | [diff] [blame] | 353 | main.log.info("Average Latency: {}".format(averageResult)) |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 354 | |
| 355 | # calculate std |
| 356 | stdResult = numpy.std(addingHostTime) |
YPZhang | 82ca589 | 2016-03-01 15:32:09 -0800 | [diff] [blame] | 357 | main.log.info("std: {}".format(stdResult)) |
YPZhang | a482c20 | 2016-02-18 17:03:07 -0800 | [diff] [blame] | 358 | |
| 359 | # write to DB file |
| 360 | main.log.info("Writing results to DS file") |
| 361 | with open(main.dbFileName, "a") as dbFile: |
| 362 | # Scale number |
| 363 | temp = str(main.numCtrls) |
| 364 | temp += ",'" + "baremetal1" + "'" |
| 365 | # average latency |
| 366 | temp += "," + str( averageResult ) |
| 367 | # std of latency |
| 368 | temp += "," + str(stdResult) |
| 369 | temp += "\n" |
| 370 | dbFile.write( temp ) |
| 371 | |
| 372 | assertion = main.TRUE |
| 373 | |
| 374 | utilities.assert_equals(expect=main.TRUE, actual=assertion, |
| 375 | onpass='Host latency test successful', |
| 376 | onfail='Host latency test failed') |
| 377 | |
| 378 | main.Mininet1.stopNet() |
| 379 | del main.scale[0] |