blob: 1d4499c1f886def78052ad6df42e77e57c85be5b [file] [log] [blame]
kelvin-onlab44147802015-07-27 17:57:31 -07001"""
2 Wrapper functions for FuncIntent
3 This functions include Onosclidriver and Mininetclidriver driver functions
4 Author: kelvin@onlab.us
5"""
6import time
7import copy
8import json
kelvin-onlab0e684682015-08-11 18:51:41 -07009import types
kelvin-onlab44147802015-07-27 17:57:31 -070010
11def __init__( self ):
12 self.default = ''
13
Jeremy2f190ca2016-01-29 15:23:57 -080014def installHostIntent( main,
15 name,
16 host1,
17 host2,
18 onosNode=0,
19 ethType="",
20 bandwidth="",
21 lambdaAlloc=False,
22 ipProto="",
23 ipAddresses="",
24 tcp="",
25 sw1="",
Jeremy Songstere7f3b342016-08-17 14:56:49 -070026 sw2="" ):
kelvin-onlab44147802015-07-27 17:57:31 -070027 """
Jeremy2f190ca2016-01-29 15:23:57 -080028 Installs a Host Intent
29
30 Description:
31 Install a host intent using
32 add-host-intent
33
34 Steps:
35 - Fetch host data if not given
36 - Add host intent
37 - Ingress device is the first sender host
38 - Egress devices are the recipient devices
39 - Ports if defined in senders or recipients
40 - MAC address ethSrc loaded from Ingress device
41 - Check intent state with retry
42 Required:
43 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
44 host1 - Dictionary for host1
45 { "name":"h8", "id":"of:0000000000000005/8" }
46 host2 - Dictionary for host2
47 { "name":"h16", "id":"of:0000000000000006/8" }
48 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -070049 onosNode - ONOS node to install the intents in main.RESTs[ ]
Jeremy2f190ca2016-01-29 15:23:57 -080050 0 by default so that it will always use the first
51 ONOS node
52 ethType - Ethernet type eg. IPV4, IPV6
53 bandwidth - Bandwidth capacity
54 lambdaAlloc - Allocate lambda, defaults to False
55 ipProto - IP protocol
56 tcp - TCP ports in the same order as the hosts in hostNames
kelvin-onlab44147802015-07-27 17:57:31 -070057 """
58
kelvin-onlab44147802015-07-27 17:57:31 -070059 assert main, "There is no main variable"
Jeremy2f190ca2016-01-29 15:23:57 -080060 assert host1, "You must specify host1"
61 assert host2, "You must specify host2"
kelvin-onlab44147802015-07-27 17:57:31 -070062
Jeremy2f190ca2016-01-29 15:23:57 -080063 global itemName # The name of this run. Used for logs.
kelvin-onlab44147802015-07-27 17:57:31 -070064 itemName = name
kelvin-onlab44147802015-07-27 17:57:31 -070065 onosNode = int( onosNode )
66
Jeremy2f190ca2016-01-29 15:23:57 -080067 main.log.info( itemName + ": Adding single point to multi point intents" )
kelvin-onlab44147802015-07-27 17:57:31 -070068
Jeremydd9bda62016-04-18 12:02:32 -070069 try:
70 if not host1.get( "id" ):
71 main.log.warn( "ID not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
72 main.log.debug( main.hostsData.get( host1.get( "name" ) ) )
73 host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "id" )
kelvin-onlab44147802015-07-27 17:57:31 -070074
Jeremydd9bda62016-04-18 12:02:32 -070075 if not host2.get( "id" ):
76 main.log.warn( "ID not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
77 host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "id" )
Jeremy Songsterae2dd452016-05-17 16:44:35 -070078 vlanId = host1.get( "vlanId" )
kelvin-onlab44147802015-07-27 17:57:31 -070079
Jeremydd9bda62016-04-18 12:02:32 -070080 # Adding host intents
81 main.log.info( itemName + ": Adding host intents" )
kelvin-onlab44147802015-07-27 17:57:31 -070082
Jeremy Songstere7f3b342016-08-17 14:56:49 -070083 intent1 = main.RESTs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
Jeremy Songsterae2dd452016-05-17 16:44:35 -070084 hostIdTwo=host2.get( "id" ),
85 vlanId=vlanId )
kelvin-onlab44147802015-07-27 17:57:31 -070086
Jeremydd9bda62016-04-18 12:02:32 -070087 # Get all intents ID in the system, time delay right after intents are added
88 time.sleep( main.addIntentSleep )
Jeremy Songstere7f3b342016-08-17 14:56:49 -070089 intentsId = main.RESTs[ 0 ].getIntentsId()
90 except( KeyError, TypeError ):
Jeremydd9bda62016-04-18 12:02:32 -070091 errorMsg = "There was a problem loading the hosts data."
92 if intentsId:
93 errorMsg += " There was a problem installing host to host intent."
94 main.log.error( errorMsg )
95 return main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -070096
Jeremy Songster306ed7a2016-07-19 10:59:07 -070097 if utilities.retry( f=checkIntentState, retValue=main.FALSE,
98 args=( main, intentsId ), sleep=main.checkIntentSleep, attempts=5 ):
99 main.assertReturnString += 'Install Intent State Passed\n'
100 if flowDuration( main ):
101 main.assertReturnString += 'Flow duration check Passed\n'
102 return intentsId
103 else:
104 main.assertReturnString += 'Flow duration check failed\n'
105 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -0800106 else:
107 main.log.error( "Host Intent did not install correctly" )
Jeremy Songster306ed7a2016-07-19 10:59:07 -0700108 main.assertReturnString += 'Install Intent State Failed\n'
Jeremy2f190ca2016-01-29 15:23:57 -0800109 return main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700110
Jeremy2f190ca2016-01-29 15:23:57 -0800111def testHostIntent( main,
112 name,
113 intentId,
114 host1,
115 host2,
116 onosNode=0,
117 sw1="s5",
118 sw2="s2",
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700119 expectedLink=0 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800120 """
121 Test a Host Intent
kelvin-onlab44147802015-07-27 17:57:31 -0700122
Jeremy2f190ca2016-01-29 15:23:57 -0800123 Description:
124 Test a host intent of given ID between given hosts
kelvin-onlab44147802015-07-27 17:57:31 -0700125
Jeremy2f190ca2016-01-29 15:23:57 -0800126 Steps:
127 - Fetch host data if not given
128 - Check Intent State
129 - Check Flow State
130 - Check Connectivity
131 - Check Lack of Connectivity Between Hosts not in the Intent
132 - Reroute
133 - Take Expected Link Down
134 - Check Intent State
135 - Check Flow State
136 - Check Topology
137 - Check Connectivity
138 - Bring Expected Link Up
139 - Check Intent State
140 - Check Flow State
141 - Check Topology
142 - Check Connectivity
143 - Remove Topology
kelvin-onlab44147802015-07-27 17:57:31 -0700144
Jeremy2f190ca2016-01-29 15:23:57 -0800145 Required:
146 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
147 intentId - intent ID to be tested ( and removed )
148 host1 - Dictionary for host1
149 { "name":"h8", "id":"of:0000000000000005/8" }
150 host2 - Dictionary for host2
151 { "name":"h16", "id":"of:0000000000000006/8" }
152 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700153 onosNode - ONOS node to install the intents in main.RESTs[ ]
Jeremy2f190ca2016-01-29 15:23:57 -0800154 0 by default so that it will always use the first
155 ONOS node
156 sw1 - First switch to bring down & up for rerouting purpose
157 sw2 - Second switch to bring down & up for rerouting purpose
158 expectedLink - Expected link when the switches are down, it should
159 be two links lower than the links before the two
160 switches are down
kelvin-onlab44147802015-07-27 17:57:31 -0700161
162 """
kelvin-onlab44147802015-07-27 17:57:31 -0700163
Jeremy2f190ca2016-01-29 15:23:57 -0800164 # Parameter Validity Check
kelvin-onlab44147802015-07-27 17:57:31 -0700165 assert main, "There is no main variable"
Jeremy2f190ca2016-01-29 15:23:57 -0800166 assert host1, "You must specify host1"
167 assert host2, "You must specify host2"
kelvin-onlab44147802015-07-27 17:57:31 -0700168
169 global itemName
170 itemName = name
Jeremy2f190ca2016-01-29 15:23:57 -0800171 tempHostsData = {}
kelvin-onlab44147802015-07-27 17:57:31 -0700172 onosNode = int( onosNode )
173
Jeremy2f190ca2016-01-29 15:23:57 -0800174 main.log.info( itemName + ": Testing Host Intent" )
kelvin-onlab44147802015-07-27 17:57:31 -0700175
Jeremydd9bda62016-04-18 12:02:32 -0700176 try:
177 if not host1.get( "id" ):
178 main.log.warn( "Id not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
179 host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "location" )
kelvin-onlab0e684682015-08-11 18:51:41 -0700180
Jeremydd9bda62016-04-18 12:02:32 -0700181 if not host2.get( "id" ):
182 main.log.warn( "Id not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
183 host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "location" )
kelvin-onlab44147802015-07-27 17:57:31 -0700184
Jeremydd9bda62016-04-18 12:02:32 -0700185 senderNames = [ host1.get( "name" ), host2.get( "name" ) ]
186 recipientNames = [ host1.get( "name" ), host2.get( "name" ) ]
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700187 vlanId = host1.get( "vlanId" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700188 except( KeyError, TypeError ):
Jeremydd9bda62016-04-18 12:02:32 -0700189 main.log.error( "There was a problem loading the hosts data." )
190 return main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700191
Jeremy2f190ca2016-01-29 15:23:57 -0800192 testResult = main.TRUE
193 main.log.info( itemName + ": Adding single point to multi point intents" )
194
195 # Check intent state
196 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
197 main.assertReturnString += 'Initial Intent State Passed\n'
198 else:
199 main.assertReturnString += 'Initial Intent State Failed\n'
200 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700201
202 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800203 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800204 main.assertReturnString += 'Initial Flow State Passed\n'
205 else:
206 main.assertReturnString += 'Intial Flow State Failed\n'
207 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700208
Jeremy2f190ca2016-01-29 15:23:57 -0800209 # Check Connectivity
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700210 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800211 main.assertReturnString += 'Initial Ping Passed\n'
212 else:
213 main.assertReturnString += 'Initial Ping Failed\n'
214 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700215
216 # Test rerouting if these variables exist
217 if sw1 and sw2 and expectedLink:
Jeremy2f190ca2016-01-29 15:23:57 -0800218 # Take link down
219 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
220 main.assertReturnString += 'Link Down Passed\n'
221 else:
222 main.assertReturnString += 'Link Down Failed\n'
223 testResult = main.FALSE
224
225 # Check intent state
226 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
227 main.assertReturnString += 'Link Down Intent State Passed\n'
228 else:
229 main.assertReturnString += 'Link Down Intent State Failed\n'
230 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700231
232 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800233 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800234 main.assertReturnString += 'Link Down Flow State Passed\n'
235 else:
236 main.assertReturnString += 'Link Down Flow State Failed\n'
237 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700238
239 # Check OnosTopology
Jeremybc6a0aa2016-02-05 14:10:08 -0800240 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ), sleep=10 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800241 main.assertReturnString += 'Link Down Topology State Passed\n'
kelvin-onlab44147802015-07-27 17:57:31 -0700242 else:
Jeremy2f190ca2016-01-29 15:23:57 -0800243 main.assertReturnString += 'Link Down Topology State Failed\n'
244 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700245
Jeremy2f190ca2016-01-29 15:23:57 -0800246 # Check Connection
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700247 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800248 main.assertReturnString += 'Link Down Pingall Passed\n'
249 else:
250 main.assertReturnString += 'Link Down Pingall Failed\n'
251 testResult = main.FALSE
252
253 # Bring link up
254 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
255 main.assertReturnString += 'Link Up Passed\n'
256 else:
257 main.assertReturnString += 'Link Up Failed\n'
258 testResult = main.FALSE
259
260 # Wait for reroute
kelvin-onlab44147802015-07-27 17:57:31 -0700261 time.sleep( main.rerouteSleep )
262
Jeremy2f190ca2016-01-29 15:23:57 -0800263 # Check Intents
264 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
265 main.assertReturnString += 'Link Up Intent State Passed\n'
266 else:
267 main.assertReturnString += 'Link Up Intent State Failed\n'
268 testResult = main.FALSE
269
kelvin-onlab44147802015-07-27 17:57:31 -0700270 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800271 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800272 main.assertReturnString += 'Link Up Flow State Passed\n'
273 else:
274 main.assertReturnString += 'Link Up Flow State Failed\n'
275 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700276
277 # Check OnosTopology
Jeremy2f190ca2016-01-29 15:23:57 -0800278 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
279 main.assertReturnString += 'Link Up Topology State Passed\n'
kelvin-onlab44147802015-07-27 17:57:31 -0700280 else:
Jeremy2f190ca2016-01-29 15:23:57 -0800281 main.assertReturnString += 'Link Up Topology State Failed\n'
282 testResult = main.FALSE
283
284 # Check Connection
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700285 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800286 main.assertReturnString += 'Link Up Pingall Passed\n'
287 else:
288 main.assertReturnString += 'Link Up Pingall Failed\n'
289 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700290
291 # Remove all intents
Jeremy2f190ca2016-01-29 15:23:57 -0800292 if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, ) ):
293 main.assertReturnString += 'Remove Intents Passed'
294 else:
295 main.assertReturnString += 'Remove Intents Failed'
296 testResult = main.FALSE
kelvin-onlab44147802015-07-27 17:57:31 -0700297
Jeremy2f190ca2016-01-29 15:23:57 -0800298 return testResult
kelvin-onlab44147802015-07-27 17:57:31 -0700299
Jeremy2f190ca2016-01-29 15:23:57 -0800300def installPointIntent( main,
301 name,
302 senders,
303 recipients,
304 onosNode=0,
305 ethType="",
306 bandwidth="",
307 lambdaAlloc=False,
308 ipProto="",
309 ipSrc="",
310 ipDst="",
311 tcpSrc="",
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700312 tcpDst="" ):
Jeremy2f190ca2016-01-29 15:23:57 -0800313 """
314 Installs a Single to Single Point Intent
315
316 Description:
317 Install a single to single point intent
318
319 Steps:
320 - Fetch host data if not given
321 - Add point intent
322 - Ingress device is the first sender device
323 - Egress device is the first recipient device
324 - Ports if defined in senders or recipients
325 - MAC address ethSrc loaded from Ingress device
326 - Check intent state with retry
327 Required:
328 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
329 senders - List of host dictionaries i.e.
330 [ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
331 recipients - List of host dictionaries i.e.
332 [ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
333 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700334 onosNode - ONOS node to install the intents in main.RESTs[ ]
Jeremy2f190ca2016-01-29 15:23:57 -0800335 0 by default so that it will always use the first
336 ONOS node
337 ethType - Ethernet type eg. IPV4, IPV6
338 bandwidth - Bandwidth capacity
339 lambdaAlloc - Allocate lambda, defaults to False
340 ipProto - IP protocol
341 tcp - TCP ports in the same order as the hosts in hostNames
342 sw1 - First switch to bring down & up for rerouting purpose
343 sw2 - Second switch to bring down & up for rerouting purpose
344 expectedLink - Expected link when the switches are down, it should
345 be two links lower than the links before the two
346 switches are down
347 """
348
349 assert main, "There is no main variable"
350 assert senders, "You must specify a sender"
351 assert recipients, "You must specify a recipient"
352 # Assert devices or main.hostsData, "You must specify devices"
353
354 global itemName # The name of this run. Used for logs.
355 itemName = name
356 onosNode = int( onosNode )
357
358 main.log.info( itemName + ": Adding single to single point intents" )
359
Jeremydd9bda62016-04-18 12:02:32 -0700360 try:
361 for sender in senders:
362 if not sender.get( "device" ):
363 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
364 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
Jeremy2f190ca2016-01-29 15:23:57 -0800365
Jeremydd9bda62016-04-18 12:02:32 -0700366 for recipient in recipients:
367 if not recipient.get( "device" ):
368 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
369 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700370 vlanId = senders[ 0 ].get( "vlanId" )
Jeremy2f190ca2016-01-29 15:23:57 -0800371
372
Jeremydd9bda62016-04-18 12:02:32 -0700373 ingressDevice = senders[ 0 ].get( "device" )
374 egressDevice = recipients[ 0 ].get( "device" )
Jeremy2f190ca2016-01-29 15:23:57 -0800375
Jeremydd9bda62016-04-18 12:02:32 -0700376 portIngress = senders[ 0 ].get( "port", "" )
377 portEgress = recipients[ 0 ].get( "port", "" )
378 main.log.debug( ingressDevice )
379 main.log.debug( egressDevice )
Jeremy2f190ca2016-01-29 15:23:57 -0800380
Jeremydd9bda62016-04-18 12:02:32 -0700381 srcMac = senders[ 0 ].get( "mac" )
382 dstMac = recipients[ 0 ].get( "mac" )
Jeremy2f190ca2016-01-29 15:23:57 -0800383
Jeremydd9bda62016-04-18 12:02:32 -0700384 ipSrc = senders[ 0 ].get( "ip" )
385 ipDst = recipients[ 0 ].get( "ip" )
Jeremy2f190ca2016-01-29 15:23:57 -0800386
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700387 intent1 = main.RESTs[ onosNode ].addPointIntent(
Jeremydd9bda62016-04-18 12:02:32 -0700388 ingressDevice=ingressDevice,
389 egressDevice=egressDevice,
390 ingressPort=portIngress,
391 egressPort=portEgress,
392 ethType=ethType,
393 ethSrc=srcMac,
394 ethDst=dstMac,
395 bandwidth=bandwidth,
396 lambdaAlloc=lambdaAlloc,
397 ipProto=ipProto,
398 ipSrc=ipSrc,
399 ipDst=ipDst,
400 tcpSrc=tcpSrc,
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700401 tcpDst=tcpDst,
402 vlanId=vlanId )
Jeremy2f190ca2016-01-29 15:23:57 -0800403
Jeremydd9bda62016-04-18 12:02:32 -0700404 time.sleep( main.addIntentSleep )
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700405 intentsId = main.RESTs[ 0 ].getIntentsId()
406 except( KeyError, TypeError ):
Jeremydd9bda62016-04-18 12:02:32 -0700407 errorMsg = "There was a problem loading the hosts data."
Jeremy Songster306ed7a2016-07-19 10:59:07 -0700408 if intentsId:
Jeremydd9bda62016-04-18 12:02:32 -0700409 errorMsg += " There was a problem installing Point to Point intent."
410 main.log.error( errorMsg )
411 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -0800412
Jeremydd9bda62016-04-18 12:02:32 -0700413 # Check intent state
Jeremy Songster306ed7a2016-07-19 10:59:07 -0700414 if utilities.retry( f=checkIntentState, retValue=main.FALSE,
415 args=( main, intentsId ), sleep=main.checkIntentSleep ):
416 main.assertReturnString += 'Install Intent State Passed\n'
417 if flowDuration( main ):
418 main.assertReturnString += 'Flow duration check Passed\n'
419 return intentsId
420 else:
421 main.assertReturnString += 'Flow duration check failed\n'
422 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -0800423 else:
Jeremy Songster306ed7a2016-07-19 10:59:07 -0700424 main.log.error( "Host Intent did not install correctly" )
425 main.assertReturnString += 'Install Intent State Failed\n'
Jeremy2f190ca2016-01-29 15:23:57 -0800426 return main.FALSE
427
Jeremy2f190ca2016-01-29 15:23:57 -0800428def testPointIntent( main,
429 name,
430 intentId,
431 senders,
432 recipients,
433 badSenders={},
434 badRecipients={},
435 onosNode=0,
436 ethType="",
437 bandwidth="",
438 lambdaAlloc=False,
439 ipProto="",
440 ipAddresses="",
441 tcp="",
442 sw1="s5",
443 sw2="s2",
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700444 expectedLink=0,
445 useTCP=False ):
Jeremy2f190ca2016-01-29 15:23:57 -0800446 """
447 Test a Point Intent
448
449 Description:
450 Test a point intent
451
452 Steps:
453 - Fetch host data if not given
454 - Check Intent State
455 - Check Flow State
456 - Check Connectivity
457 - Check Lack of Connectivity Between Hosts not in the Intent
458 - Reroute
459 - Take Expected Link Down
460 - Check Intent State
461 - Check Flow State
462 - Check Topology
463 - Check Connectivity
464 - Bring Expected Link Up
465 - Check Intent State
466 - Check Flow State
467 - Check Topology
468 - Check Connectivity
469 - Remove Topology
470
471 Required:
472 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
473
474 senders - List of host dictionaries i.e.
475 { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
476 recipients - List of host dictionaries i.e.
477 { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
478 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700479 onosNode - ONOS node to install the intents in main.RESTs[ ]
Jeremy2f190ca2016-01-29 15:23:57 -0800480 0 by default so that it will always use the first
481 ONOS node
482 ethType - Ethernet type eg. IPV4, IPV6
483 bandwidth - Bandwidth capacity
484 lambdaAlloc - Allocate lambda, defaults to False
485 ipProto - IP protocol
486 tcp - TCP ports in the same order as the hosts in hostNames
487 sw1 - First switch to bring down & up for rerouting purpose
488 sw2 - Second switch to bring down & up for rerouting purpose
489 expectedLink - Expected link when the switches are down, it should
490 be two links lower than the links before the two
491 switches are down
492
493 """
494
495 # Parameter Validity Check
496 assert main, "There is no main variable"
497 assert senders, "You must specify a sender"
498 assert recipients, "You must specify a recipient"
499
500 global itemName
501 itemName = name
502 tempHostsData = {}
503 onosNode = int( onosNode )
504
505 main.log.info( itemName + ": Testing Point Intent" )
506
Jeremydd9bda62016-04-18 12:02:32 -0700507 try:
508 # Names for scapy
509 senderNames = [ x.get( "name" ) for x in senders ]
510 recipientNames = [ x.get( "name" ) for x in recipients ]
511 badSenderNames = [ x.get( "name" ) for x in badSenders ]
512 badRecipientNames = [ x.get( "name" ) for x in badRecipients ]
Jeremy2f190ca2016-01-29 15:23:57 -0800513
Jeremydd9bda62016-04-18 12:02:32 -0700514 for sender in senders:
515 if not sender.get( "device" ):
516 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
517 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
Jeremy2f190ca2016-01-29 15:23:57 -0800518
Jeremydd9bda62016-04-18 12:02:32 -0700519 for recipient in recipients:
520 if not recipient.get( "device" ):
521 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
522 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700523 vlanId=senders[ 0 ].get( "vlanId" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700524 except( KeyError, TypeError ):
Jeremydd9bda62016-04-18 12:02:32 -0700525 main.log.error( "There was a problem loading the hosts data." )
526 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -0800527
528 testResult = main.TRUE
529 main.log.info( itemName + ": Testing point intents" )
530
531 # Check intent state
532 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
533 main.assertReturnString += 'Initial Intent State Passed\n'
534 else:
535 main.assertReturnString += 'Initial Intent State Failed\n'
536 testResult = main.FALSE
537
538 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800539 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800540 main.assertReturnString += 'Initial Flow State Passed\n'
541 else:
542 main.assertReturnString += 'Intial Flow State Failed\n'
543 testResult = main.FALSE
544
545 # Check Connectivity
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700546 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800547 main.assertReturnString += 'Initial Ping Passed\n'
548 else:
549 main.assertReturnString += 'Initial Ping Failed\n'
550 testResult = main.FALSE
551
552 # Check connections that shouldn't work
553 if badSenderNames:
554 main.log.info( "Checking that packets from incorrect sender do not go through" )
555 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, badSenderNames, recipientNames ), kwargs={ "expectFailure":True } ):
556 main.assertReturnString += 'Bad Sender Ping Passed\n'
557 else:
558 main.assertReturnString += 'Bad Sender Ping Failed\n'
559 testResult = main.FALSE
560
561 if badRecipientNames:
562 main.log.info( "Checking that packets to incorrect recipients do not go through" )
563 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, badRecipientNames ), kwargs={ "expectFailure":True } ):
564 main.assertReturnString += 'Bad Recipient Ping Passed\n'
565 else:
566 main.assertReturnString += 'Bad Recipient Ping Failed\n'
567 testResult = main.FALSE
568
569 # Test rerouting if these variables exist
570 if sw1 and sw2 and expectedLink:
571 # Take link down
572 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
573 main.assertReturnString += 'Link Down Passed\n'
574 else:
575 main.assertReturnString += 'Link Down Failed\n'
576 testResult = main.FALSE
577
578 # Check intent state
579 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
580 main.assertReturnString += 'Link Down Intent State Passed\n'
581 else:
582 main.assertReturnString += 'Link Down Intent State Failed\n'
583 testResult = main.FALSE
584
585 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800586 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800587 main.assertReturnString += 'Link Down Flow State Passed\n'
588 else:
589 main.assertReturnString += 'Link Down Flow State Failed\n'
590 testResult = main.FALSE
591
592 # Check OnosTopology
Jeremybc6a0aa2016-02-05 14:10:08 -0800593 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ), sleep=10 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800594 main.assertReturnString += 'Link Down Topology State Passed\n'
595 else:
596 main.assertReturnString += 'Link Down Topology State Failed\n'
597 testResult = main.FALSE
598
599 # Check Connection
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700600 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800601 main.assertReturnString += 'Link Down Pingall Passed\n'
602 else:
603 main.assertReturnString += 'Link Down Pingall Failed\n'
604 testResult = main.FALSE
605
606 # Bring link up
607 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
608 main.assertReturnString += 'Link Up Passed\n'
609 else:
610 main.assertReturnString += 'Link Up Failed\n'
611 testResult = main.FALSE
612
613 # Wait for reroute
614 time.sleep( main.rerouteSleep )
615
616 # Check Intents
617 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
618 main.assertReturnString += 'Link Up Intent State Passed\n'
619 else:
620 main.assertReturnString += 'Link Up Intent State Failed\n'
621 testResult = main.FALSE
622
623 # Check flows count in each node
Jeremybc6a0aa2016-02-05 14:10:08 -0800624 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
Jeremy2f190ca2016-01-29 15:23:57 -0800625 main.assertReturnString += 'Link Up Flow State Passed\n'
626 else:
627 main.assertReturnString += 'Link Up Flow State Failed\n'
628 testResult = main.FALSE
629
630 # Check OnosTopology
631 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
632 main.assertReturnString += 'Link Up Topology State Passed\n'
633 else:
634 main.assertReturnString += 'Link Up Topology State Failed\n'
635 testResult = main.FALSE
636
637 # Check Connection
Jeremy Songsterae2dd452016-05-17 16:44:35 -0700638 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
Jeremy2f190ca2016-01-29 15:23:57 -0800639 main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
640 else:
641 main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
642 testResult = main.FALSE
643
644 # Remove all intents
645 if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, ) ):
646 main.assertReturnString += 'Remove Intents Passed'
647 else:
648 main.assertReturnString += 'Remove Intents Failed'
649 testResult = main.FALSE
650
651 return testResult
kelvin-onlab44147802015-07-27 17:57:31 -0700652
kelvin-onlab0e684682015-08-11 18:51:41 -0700653def pointIntentTcp( main,
654 name,
655 host1,
656 host2,
657 onosNode=0,
658 deviceId1="",
659 deviceId2="",
660 port1="",
661 port2="",
662 ethType="",
663 mac1="",
664 mac2="",
665 bandwidth="",
666 lambdaAlloc=False,
667 ipProto="",
668 ip1="",
669 ip2="",
670 tcp1="",
671 tcp2="",
672 sw1="",
673 sw2="",
674 expectedLink=0 ):
675
676 """
677 Description:
678 Verify add-point-intent only for TCP
679 Steps:
680 - Get device ids | ports
681 - Add point intents
682 - Check intents
683 - Verify flows
684 - Ping hosts
685 - Reroute
686 - Link down
687 - Verify flows
688 - Check topology
689 - Ping hosts
690 - Link up
691 - Verify flows
692 - Check topology
693 - Ping hosts
694 - Remove intents
695 Required:
696 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
697 host1 - Name of first host
698 host2 - Name of second host
699 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700700 onosNode - ONOS node to install the intents in main.RESTs[ ]
kelvin-onlab0e684682015-08-11 18:51:41 -0700701 0 by default so that it will always use the first
702 ONOS node
703 deviceId1 - ONOS device id of the first switch, the same as the
704 location of the first host eg. of:0000000000000001/1,
705 located at device 1 port 1
706 deviceId2 - ONOS device id of the second switch
707 port1 - The port number where the first host is attached
708 port2 - The port number where the second host is attached
709 ethType - Ethernet type eg. IPV4, IPV6
710 mac1 - Mac address of first host
711 mac2 - Mac address of the second host
712 bandwidth - Bandwidth capacity
713 lambdaAlloc - Allocate lambda, defaults to False
714 ipProto - IP protocol
715 ip1 - IP address of first host
716 ip2 - IP address of second host
717 tcp1 - TCP port of first host
718 tcp2 - TCP port of second host
719 sw1 - First switch to bring down & up for rerouting purpose
720 sw2 - Second switch to bring down & up for rerouting purpose
721 expectedLink - Expected link when the switches are down, it should
722 be two links lower than the links before the two
723 switches are down
724 """
725
726 assert main, "There is no main variable"
727 assert name, "variable name is empty"
728 assert host1 and host2, "You must specify hosts"
729
730 global itemName
731 itemName = name
732 host1 = host1
733 host2 = host2
734 hostNames = [ host1, host2 ]
735 intentsId = []
736
737 iperfResult = main.TRUE
738 intentResult = main.TRUE
739 removeIntentResult = main.TRUE
740 flowResult = main.TRUE
741 topoResult = main.TRUE
742 linkDownResult = main.TRUE
743 linkUpResult = main.TRUE
744 onosNode = int( onosNode )
745
746 # Adding bidirectional point intents
747 main.log.info( itemName + ": Adding point intents" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700748 intent1 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
kelvin-onlab0e684682015-08-11 18:51:41 -0700749 egressDevice=deviceId2,
750 ingressPort=port1,
751 egressPort=port2,
752 ethType=ethType,
753 ethSrc=mac1,
754 ethDst=mac2,
755 bandwidth=bandwidth,
756 lambdaAlloc=lambdaAlloc,
757 ipProto=ipProto,
758 ipSrc=ip1,
759 ipDst=ip2,
760 tcpSrc=tcp1,
761 tcpDst="" )
762
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700763 intent2 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
kelvin-onlab0e684682015-08-11 18:51:41 -0700764 egressDevice=deviceId1,
765 ingressPort=port2,
766 egressPort=port1,
767 ethType=ethType,
768 ethSrc=mac2,
769 ethDst=mac1,
770 bandwidth=bandwidth,
771 lambdaAlloc=lambdaAlloc,
772 ipProto=ipProto,
773 ipSrc=ip2,
774 ipDst=ip1,
775 tcpSrc=tcp2,
776 tcpDst="" )
777
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700778 intent3 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
kelvin-onlab0e684682015-08-11 18:51:41 -0700779 egressDevice=deviceId2,
780 ingressPort=port1,
781 egressPort=port2,
782 ethType=ethType,
783 ethSrc=mac1,
784 ethDst=mac2,
785 bandwidth=bandwidth,
786 lambdaAlloc=lambdaAlloc,
787 ipProto=ipProto,
788 ipSrc=ip1,
789 ipDst=ip2,
790 tcpSrc="",
791 tcpDst=tcp2 )
792
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700793 intent4 = main.RESTs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
kelvin-onlab0e684682015-08-11 18:51:41 -0700794 egressDevice=deviceId1,
795 ingressPort=port2,
796 egressPort=port1,
797 ethType=ethType,
798 ethSrc=mac2,
799 ethDst=mac1,
800 bandwidth=bandwidth,
801 lambdaAlloc=lambdaAlloc,
802 ipProto=ipProto,
803 ipSrc=ip2,
804 ipDst=ip1,
805 tcpSrc="",
806 tcpDst=tcp1 )
807
808 # Get all intents ID in the system, time delay right after intents are added
809 time.sleep( main.addIntentSleep )
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700810 intentsId = main.RESTs[ 0 ].getIntentsId()
kelvin-onlab0e684682015-08-11 18:51:41 -0700811 # Check intents state
812 time.sleep( main.checkIntentSleep )
813 intentResult = checkIntentState( main, intentsId )
814 # Check flows count in each node
815 checkFlowsCount( main )
816
817 # Check intents state again if first check fails...
818 if not intentResult:
819 intentResult = checkIntentState( main, intentsId )
820
821 # Check flows count in each node
822 checkFlowsCount( main )
823
824 # Verify flows
825 checkFlowsState( main )
826
827 # Run iperf to both host
828 iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
829 host2, 10 )
830
831 # Test rerouting if these variables exist
832 if sw1 and sw2 and expectedLink:
833 # link down
834 linkDownResult = link( main, sw1, sw2, "down" )
835 intentResult = intentResult and checkIntentState( main, intentsId )
836
837 # Check flows count in each node
838 checkFlowsCount( main )
839 # Verify flows
840 checkFlowsState( main )
841
842 # Check OnosTopology
843 topoResult = checkTopology( main, expectedLink )
844
845 # Run iperf to both host
846 iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
847 host2, 10 )
848
849 intentResult = checkIntentState( main, intentsId )
850
851 # Checks ONOS state in link down
852 if linkDownResult and topoResult and iperfResult and intentResult:
853 main.log.info( itemName + ": Successfully brought link down" )
854 else:
855 main.log.error( itemName + ": Failed to bring link down" )
856
857 # link up
858 linkUpResult = link( main, sw1, sw2, "up" )
859 time.sleep( main.rerouteSleep )
860
861 # Check flows count in each node
862 checkFlowsCount( main )
863 # Verify flows
864 checkFlowsState( main )
865
866 # Check OnosTopology
867 topoResult = checkTopology( main, main.numLinks )
868
869 # Run iperf to both host
870 iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
871 host2, 10 )
872
873 intentResult = checkIntentState( main, intentsId )
874
875 # Checks ONOS state in link up
876 if linkUpResult and topoResult and iperfResult and intentResult:
877 main.log.info( itemName + ": Successfully brought link back up" )
878 else:
879 main.log.error( itemName + ": Failed to bring link back up" )
880
881 # Remove all intents
882 removeIntentResult = removeAllIntents( main )
883
884 stepResult = iperfResult and linkDownResult and linkUpResult \
885 and intentResult and removeIntentResult
886
887 return stepResult
888
kelvin-onlab44147802015-07-27 17:57:31 -0700889def singleToMultiIntent( main,
890 name,
891 hostNames,
892 onosNode=0,
893 devices="",
894 ports=None,
895 ethType="",
896 macs=None,
897 bandwidth="",
898 lambdaAlloc=False,
899 ipProto="",
900 ipAddresses="",
901 tcp="",
902 sw1="",
903 sw2="",
904 expectedLink=0 ):
905 """
906 Verify Single to Multi Point intents
907 NOTE:If main.hostsData is not defined, variables data should be passed
908 in the same order index wise. All devices in the list should have the
909 same format, either all the devices have its port or it doesn't.
910 eg. hostName = [ 'h1', 'h2' ,.. ]
911 devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
912 ports = [ '1', '1', ..]
913 ...
914 Description:
915 Verify add-single-to-multi-intent iterates through the list of given
916 host | devices and add intents
917 Steps:
918 - Get device ids | ports
919 - Add single to multi point intents
920 - Check intents
921 - Verify flows
922 - Ping hosts
923 - Reroute
924 - Link down
925 - Verify flows
926 - Check topology
927 - Ping hosts
928 - Link up
929 - Verify flows
930 - Check topology
931 - Ping hosts
932 - Remove intents
933 Required:
934 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
935 hostNames - List of host names
936 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -0700937 onosNode - ONOS node to install the intents in main.RESTs[ ]
kelvin-onlab44147802015-07-27 17:57:31 -0700938 0 by default so that it will always use the first
939 ONOS node
940 devices - List of device ids in the same order as the hosts
941 in hostNames
942 ports - List of port numbers in the same order as the device in
943 devices
944 ethType - Ethernet type eg. IPV4, IPV6
945 macs - List of hosts mac address in the same order as the hosts in
946 hostNames
947 bandwidth - Bandwidth capacity
948 lambdaAlloc - Allocate lambda, defaults to False
949 ipProto - IP protocol
950 ipAddresses - IP addresses of host in the same order as the hosts in
951 hostNames
952 tcp - TCP ports in the same order as the hosts in hostNames
953 sw1 - First switch to bring down & up for rerouting purpose
954 sw2 - Second switch to bring down & up for rerouting purpose
955 expectedLink - Expected link when the switches are down, it should
956 be two links lower than the links before the two
957 switches are down
958 """
959
960 assert main, "There is no main variable"
961 assert hostNames, "You must specify hosts"
962 assert devices or main.hostsData, "You must specify devices"
963
964 global itemName
965 itemName = name
966 tempHostsData = {}
967 intentsId = []
968 onosNode = int( onosNode )
969
970 macsDict = {}
971 ipDict = {}
972 if hostNames and devices:
973 if len( hostNames ) != len( devices ):
974 main.log.debug( "hosts and devices does not have the same length" )
975 #print "len hostNames = ", len( hostNames )
976 #print "len devices = ", len( devices )
977 return main.FALSE
978 if ports:
979 if len( ports ) != len( devices ):
980 main.log.error( "Ports and devices does " +
981 "not have the same length" )
982 #print "len devices = ", len( devices )
983 #print "len ports = ", len( ports )
984 return main.FALSE
985 else:
986 main.log.info( "Device Ports are not specified" )
987 if macs:
988 for i in range( len( devices ) ):
989 macsDict[ devices[ i ] ] = macs[ i ]
990
991 elif hostNames and not devices and main.hostsData:
992 devices = []
993 main.log.info( "singleToMultiIntent function is using main.hostsData" )
994 for host in hostNames:
995 devices.append( main.hostsData.get( host ).get( 'location' ) )
996 macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
997 main.hostsData.get( host ).get( 'mac' )
998 ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
999 main.hostsData.get( host ).get( 'ipAddresses' )
1000 #print main.hostsData
1001
1002 #print 'host names = ', hostNames
1003 #print 'devices = ', devices
1004 #print "macsDict = ", macsDict
1005
1006 pingResult = main.TRUE
1007 intentResult = main.TRUE
1008 removeIntentResult = main.TRUE
1009 flowResult = main.TRUE
1010 topoResult = main.TRUE
1011 linkDownResult = main.TRUE
1012 linkUpResult = main.TRUE
1013
1014 devicesCopy = copy.copy( devices )
1015 if ports:
1016 portsCopy = copy.copy( ports )
1017 main.log.info( itemName + ": Adding single point to multi point intents" )
1018
1019 # Check flows count in each node
1020 checkFlowsCount( main )
1021
1022 # Adding bidirectional point intents
1023 for i in range( len( devices ) ):
1024 ingressDevice = devicesCopy[ i ]
1025 egressDeviceList = copy.copy( devicesCopy )
1026 egressDeviceList.remove( ingressDevice )
1027 if ports:
1028 portIngress = portsCopy[ i ]
1029 portEgressList = copy.copy( portsCopy )
1030 del portEgressList[ i ]
1031 else:
1032 portIngress = ""
1033 portEgressList = None
1034 if not macsDict:
1035 srcMac = ""
1036 else:
1037 srcMac = macsDict[ ingressDevice ]
1038 if srcMac == None:
1039 main.log.debug( "There is no MAC in device - " + ingressDevice )
1040 srcMac = ""
1041
1042 intentsId.append(
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001043 main.RESTs[ onosNode ].addSinglepointToMultipointIntent(
kelvin-onlab44147802015-07-27 17:57:31 -07001044 ingressDevice=ingressDevice,
1045 egressDeviceList=egressDeviceList,
1046 portIngress=portIngress,
1047 portEgressList=portEgressList,
1048 ethType=ethType,
1049 ethSrc=srcMac,
1050 bandwidth=bandwidth,
1051 lambdaAlloc=lambdaAlloc,
1052 ipProto=ipProto,
1053 ipSrc="",
1054 ipDst="",
1055 tcpSrc="",
1056 tcpDst="" ) )
1057
1058 # Wait some time for the flow to go through when using multi instance
1059 pingResult = pingallHosts( main, hostNames )
1060
1061 # Check intents state
1062 time.sleep( main.checkIntentSleep )
1063 intentResult = checkIntentState( main, intentsId )
1064
1065 # Check intents state again if first check fails...
1066 if not intentResult:
1067 intentResult = checkIntentState( main, intentsId )
1068
1069 # Check flows count in each node
1070 checkFlowsCount( main )
1071 # Verify flows
1072 checkFlowsState( main )
1073
1074 pingResult = pingResult and pingallHosts( main, hostNames )
1075
1076 # Test rerouting if these variables exist
1077 if sw1 and sw2 and expectedLink:
1078 # link down
1079 linkDownResult = link( main, sw1, sw2, "down" )
1080 intentResult = intentResult and checkIntentState( main, intentsId )
1081
1082 # Check flows count in each node
1083 checkFlowsCount( main )
1084 # Verify flows
1085 checkFlowsState( main )
1086
1087 # Check OnosTopology
1088 topoResult = checkTopology( main, expectedLink )
1089
1090 # Ping hosts
1091 pingResult = pingResult and pingallHosts( main, hostNames )
1092
1093 intentResult = checkIntentState( main, intentsId )
1094
1095 # Checks ONOS state in link down
1096 if linkDownResult and topoResult and pingResult and intentResult:
1097 main.log.info( itemName + ": Successfully brought link down" )
1098 else:
1099 main.log.error( itemName + ": Failed to bring link down" )
1100
1101 # link up
1102 linkUpResult = link( main, sw1, sw2, "up" )
1103 time.sleep( main.rerouteSleep )
1104
1105 # Check flows count in each node
1106 checkFlowsCount( main )
1107 # Verify flows
1108 checkFlowsState( main )
1109
1110 # Check OnosTopology
1111 topoResult = checkTopology( main, main.numLinks )
1112
1113 # Ping hosts
1114 pingResult = pingResult and pingallHosts( main, hostNames )
1115
1116 intentResult = checkIntentState( main, intentsId )
1117
1118 # Checks ONOS state in link up
1119 if linkUpResult and topoResult and pingResult and intentResult:
1120 main.log.info( itemName + ": Successfully brought link back up" )
1121 else:
1122 main.log.error( itemName + ": Failed to bring link back up" )
1123
1124 # Remove all intents
1125 removeIntentResult = removeAllIntents( main, intentsId )
1126
1127 stepResult = pingResult and linkDownResult and linkUpResult \
1128 and intentResult and removeIntentResult
1129
1130 return stepResult
1131
1132def multiToSingleIntent( main,
1133 name,
1134 hostNames,
1135 onosNode=0,
1136 devices="",
1137 ports=None,
1138 ethType="",
1139 macs=None,
1140 bandwidth="",
1141 lambdaAlloc=False,
1142 ipProto="",
1143 ipAddresses="",
1144 tcp="",
1145 sw1="",
1146 sw2="",
1147 expectedLink=0 ):
1148 """
1149 Verify Single to Multi Point intents
1150 NOTE:If main.hostsData is not defined, variables data should be passed in the
1151 same order index wise. All devices in the list should have the same
1152 format, either all the devices have its port or it doesn't.
1153 eg. hostName = [ 'h1', 'h2' ,.. ]
1154 devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
1155 ports = [ '1', '1', ..]
1156 ...
1157 Description:
1158 Verify add-multi-to-single-intent
1159 Steps:
1160 - Get device ids | ports
1161 - Add multi to single point intents
1162 - Check intents
1163 - Verify flows
1164 - Ping hosts
1165 - Reroute
1166 - Link down
1167 - Verify flows
1168 - Check topology
1169 - Ping hosts
1170 - Link up
1171 - Verify flows
1172 - Check topology
1173 - Ping hosts
1174 - Remove intents
1175 Required:
1176 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
1177 hostNames - List of host names
1178 Optional:
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001179 onosNode - ONOS node to install the intents in main.RESTs[ ]
kelvin-onlab44147802015-07-27 17:57:31 -07001180 0 by default so that it will always use the first
1181 ONOS node
1182 devices - List of device ids in the same order as the hosts
1183 in hostNames
1184 ports - List of port numbers in the same order as the device in
1185 devices
1186 ethType - Ethernet type eg. IPV4, IPV6
1187 macs - List of hosts mac address in the same order as the hosts in
1188 hostNames
1189 bandwidth - Bandwidth capacity
1190 lambdaAlloc - Allocate lambda, defaults to False
1191 ipProto - IP protocol
1192 ipAddresses - IP addresses of host in the same order as the hosts in
1193 hostNames
1194 tcp - TCP ports in the same order as the hosts in hostNames
1195 sw1 - First switch to bring down & up for rerouting purpose
1196 sw2 - Second switch to bring down & up for rerouting purpose
1197 expectedLink - Expected link when the switches are down, it should
1198 be two links lower than the links before the two
1199 switches are down
1200 """
1201
1202 assert main, "There is no main variable"
1203 assert hostNames, "You must specify hosts"
1204 assert devices or main.hostsData, "You must specify devices"
1205
1206 global itemName
1207 itemName = name
1208 tempHostsData = {}
1209 intentsId = []
1210 onosNode = int( onosNode )
1211
1212 macsDict = {}
1213 ipDict = {}
1214 if hostNames and devices:
1215 if len( hostNames ) != len( devices ):
1216 main.log.debug( "hosts and devices does not have the same length" )
1217 #print "len hostNames = ", len( hostNames )
1218 #print "len devices = ", len( devices )
1219 return main.FALSE
1220 if ports:
1221 if len( ports ) != len( devices ):
1222 main.log.error( "Ports and devices does " +
1223 "not have the same length" )
1224 #print "len devices = ", len( devices )
1225 #print "len ports = ", len( ports )
1226 return main.FALSE
1227 else:
1228 main.log.info( "Device Ports are not specified" )
1229 if macs:
1230 for i in range( len( devices ) ):
1231 macsDict[ devices[ i ] ] = macs[ i ]
1232 elif hostNames and not devices and main.hostsData:
1233 devices = []
1234 main.log.info( "multiToSingleIntent function is using main.hostsData" )
1235 for host in hostNames:
1236 devices.append( main.hostsData.get( host ).get( 'location' ) )
1237 macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
1238 main.hostsData.get( host ).get( 'mac' )
1239 ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
1240 main.hostsData.get( host ).get( 'ipAddresses' )
1241 #print main.hostsData
1242
1243 #print 'host names = ', hostNames
1244 #print 'devices = ', devices
1245 #print "macsDict = ", macsDict
1246
1247 pingResult = main.TRUE
1248 intentResult = main.TRUE
1249 removeIntentResult = main.TRUE
1250 flowResult = main.TRUE
1251 topoResult = main.TRUE
1252 linkDownResult = main.TRUE
1253 linkUpResult = main.TRUE
1254
1255 devicesCopy = copy.copy( devices )
1256 if ports:
1257 portsCopy = copy.copy( ports )
1258 main.log.info( itemName + ": Adding multi point to single point intents" )
1259
1260 # Check flows count in each node
1261 checkFlowsCount( main )
1262
1263 # Adding bidirectional point intents
1264 for i in range( len( devices ) ):
1265 egressDevice = devicesCopy[ i ]
1266 ingressDeviceList = copy.copy( devicesCopy )
1267 ingressDeviceList.remove( egressDevice )
1268 if ports:
1269 portEgress = portsCopy[ i ]
1270 portIngressList = copy.copy( portsCopy )
1271 del portIngressList[ i ]
1272 else:
1273 portEgress = ""
1274 portIngressList = None
1275 if not macsDict:
1276 dstMac = ""
1277 else:
1278 dstMac = macsDict[ egressDevice ]
1279 if dstMac == None:
1280 main.log.debug( "There is no MAC in device - " + egressDevice )
1281 dstMac = ""
1282
1283 intentsId.append(
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001284 main.RESTs[ onosNode ].addMultipointToSinglepointIntent(
kelvin-onlab44147802015-07-27 17:57:31 -07001285 ingressDeviceList=ingressDeviceList,
1286 egressDevice=egressDevice,
1287 portIngressList=portIngressList,
1288 portEgress=portEgress,
1289 ethType=ethType,
1290 ethDst=dstMac,
1291 bandwidth=bandwidth,
1292 lambdaAlloc=lambdaAlloc,
1293 ipProto=ipProto,
1294 ipSrc="",
1295 ipDst="",
1296 tcpSrc="",
1297 tcpDst="" ) )
1298
1299 pingResult = pingallHosts( main, hostNames )
1300
1301 # Check intents state
1302 time.sleep( main.checkIntentSleep )
1303 intentResult = checkIntentState( main, intentsId )
1304
1305 # Check intents state again if first check fails...
1306 if not intentResult:
1307 intentResult = checkIntentState( main, intentsId )
1308
1309 # Check flows count in each node
1310 checkFlowsCount( main )
1311 # Verify flows
1312 checkFlowsState( main )
1313
1314 # Ping hosts
1315 pingResult = pingResult and pingallHosts( main, hostNames )
1316 # Ping hosts again...
1317 pingResult = pingResult and pingallHosts( main, hostNames )
1318
1319 # Test rerouting if these variables exist
1320 if sw1 and sw2 and expectedLink:
1321 # link down
1322 linkDownResult = link( main, sw1, sw2, "down" )
1323 intentResult = intentResult and checkIntentState( main, intentsId )
1324
1325 # Check flows count in each node
1326 checkFlowsCount( main )
1327 # Verify flows
1328 checkFlowsState( main )
1329
1330 # Check OnosTopology
1331 topoResult = checkTopology( main, expectedLink )
1332
1333 # Ping hosts
1334 pingResult = pingResult and pingallHosts( main, hostNames )
1335
1336 intentResult = checkIntentState( main, intentsId )
1337
1338 # Checks ONOS state in link down
1339 if linkDownResult and topoResult and pingResult and intentResult:
1340 main.log.info( itemName + ": Successfully brought link down" )
1341 else:
1342 main.log.error( itemName + ": Failed to bring link down" )
1343
1344 # link up
1345 linkUpResult = link( main, sw1, sw2, "up" )
1346 time.sleep( main.rerouteSleep )
1347
1348 # Check flows count in each node
1349 checkFlowsCount( main )
1350 # Verify flows
1351 checkFlowsState( main )
1352
1353 # Check OnosTopology
1354 topoResult = checkTopology( main, main.numLinks )
1355
1356 # Ping hosts
1357 pingResult = pingResult and pingallHosts( main, hostNames )
1358
1359 intentResult = checkIntentState( main, intentsId )
1360
1361 # Checks ONOS state in link up
1362 if linkUpResult and topoResult and pingResult and intentResult:
1363 main.log.info( itemName + ": Successfully brought link back up" )
1364 else:
1365 main.log.error( itemName + ": Failed to bring link back up" )
1366
1367 # Remove all intents
1368 removeIntentResult = removeAllIntents( main, intentsId )
1369
1370 stepResult = pingResult and linkDownResult and linkUpResult \
1371 and intentResult and removeIntentResult
1372
1373 return stepResult
1374
kelvin-onlab0e684682015-08-11 18:51:41 -07001375def pingallHosts( main, hostList ):
kelvin-onlab44147802015-07-27 17:57:31 -07001376 # Ping all host in the hosts list variable
1377 print "Pinging : ", hostList
1378 pingResult = main.TRUE
kelvin-onlab0e684682015-08-11 18:51:41 -07001379 pingResult = main.Mininet1.pingallHosts( hostList )
kelvin-onlab44147802015-07-27 17:57:31 -07001380 return pingResult
1381
kelvin-onlab0e684682015-08-11 18:51:41 -07001382def getHostsData( main, hostList ):
kelvin-onlab44147802015-07-27 17:57:31 -07001383 """
1384 Use fwd app and pingall to discover all the hosts
1385 """
1386
1387 activateResult = main.TRUE
1388 appCheck = main.TRUE
1389 getDataResult = main.TRUE
1390 main.log.info( "Activating reactive forwarding app " )
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001391 activateResult = main.RESTs[ 0 ].activateApp( "org.onosproject.fwd" )
kelvin-onlab44147802015-07-27 17:57:31 -07001392 if not activateResult:
1393 main.log.error( "Something went wrong installing fwd app" )
1394 time.sleep( main.fwdSleep )
kelvin-onlab0e684682015-08-11 18:51:41 -07001395 if isinstance( hostList[ 0 ], types.StringType ):
1396 main.Mininet1.pingallHosts( hostList )
1397 elif isinstance( hostList[ 0 ], types.ListType ):
1398 for i in xrange( len( hostList ) ):
1399 main.Mininet1.pingallHosts( hostList[ i ] )
1400
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001401 hostsJson = json.loads( main.RESTs[ 0 ].hosts() )
kelvin-onlab44147802015-07-27 17:57:31 -07001402 hosts = main.Mininet1.getHosts().keys()
1403 # TODO: Make better use of new getHosts function
1404 for host in hosts:
1405 main.hostsData[ host ] = {}
1406 main.hostsData[ host ][ 'mac' ] = \
1407 main.Mininet1.getMacAddress( host ).upper()
1408 for hostj in hostsJson:
1409 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
1410 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
1411 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
1412 main.hostsData[ host ][ 'location' ] = \
1413 hostj[ 'location' ][ 'elementId' ] + '/' + \
1414 hostj[ 'location' ][ 'port' ]
1415 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
1416
1417 main.log.info( "Deactivating reactive forwarding app " )
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001418 deactivateResult = main.RESTs[ 0 ].deactivateApp( "org.onosproject.fwd" )
kelvin-onlab44147802015-07-27 17:57:31 -07001419 if activateResult and deactivateResult and main.hostsData:
1420 main.log.info( "Successfully used fwd app to discover hosts " )
1421 getDataResult = main.TRUE
1422 else:
1423 main.log.info( "Failed to use fwd app to discover hosts " )
1424 getDataResult = main.FALSE
1425
1426 print main.hostsData
1427
1428 return getDataResult
1429
1430def checkTopology( main, expectedLink ):
1431 statusResult = main.TRUE
1432 # Check onos topology
1433 main.log.info( itemName + ": Checking ONOS topology " )
1434
1435 for i in range( main.numCtrls ):
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001436 statusResult = main.RESTs[ i ].checkStatus( main.numSwitch,
kelvin-onlab44147802015-07-27 17:57:31 -07001437 expectedLink )\
1438 and statusResult
1439 if not statusResult:
1440 main.log.error( itemName + ": Topology mismatch" )
1441 else:
1442 main.log.info( itemName + ": Topology match" )
1443 return statusResult
1444
1445def checkIntentState( main, intentsId ):
1446 """
1447 This function will check intent state to make sure all the intents
1448 are in INSTALLED state
1449 """
1450
1451 intentResult = main.TRUE
1452 results = []
1453
1454 main.log.info( itemName + ": Checking intents state" )
1455 # First check of intents
1456 for i in range( main.numCtrls ):
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001457 tempResult = main.RESTs[ i ].checkIntentState( intentsId=intentsId )
kelvin-onlab44147802015-07-27 17:57:31 -07001458 results.append( tempResult )
1459
1460 expectedState = [ 'INSTALLED', 'INSTALLING' ]
1461
1462 if all( result == main.TRUE for result in results ):
1463 main.log.info( itemName + ": Intents are installed correctly" )
1464 else:
1465 # Wait for at least 5 second before checking the intents again
Jeremy2f190ca2016-01-29 15:23:57 -08001466 main.log.error( "Intents are not installed correctly. Waiting 5 sec" )
kelvin-onlab44147802015-07-27 17:57:31 -07001467 time.sleep( 5 )
1468 results = []
1469 # Second check of intents since some of the intents may be in
1470 # INSTALLING state, they should be in INSTALLED at this time
1471 for i in range( main.numCtrls ):
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001472 tempResult = main.RESTs[ i ].checkIntentState( intentsId=intentsId )
kelvin-onlab44147802015-07-27 17:57:31 -07001473 results.append( tempResult )
1474 if all( result == main.TRUE for result in results ):
1475 main.log.info( itemName + ": Intents are installed correctly" )
Jeremy2f190ca2016-01-29 15:23:57 -08001476 intentResult = main.TRUE
kelvin-onlab44147802015-07-27 17:57:31 -07001477 else:
1478 main.log.error( itemName + ": Intents are NOT installed correctly" )
1479 intentResult = main.FALSE
1480
1481 return intentResult
1482
1483def checkFlowsState( main ):
1484
1485 main.log.info( itemName + ": Check flows state" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001486 checkFlowsResult = main.RESTs[ 0 ].checkFlowsState()
kelvin-onlab44147802015-07-27 17:57:31 -07001487 return checkFlowsResult
1488
1489def link( main, sw1, sw2, option):
1490
1491 # link down
1492 main.log.info( itemName + ": Bring link " + option + "between " +
1493 sw1 + " and " + sw2 )
1494 linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
1495 return linkResult
1496
1497def removeAllIntents( main ):
1498 """
1499 Remove all intents in the intentsId
1500 """
1501
1502 onosSummary = []
1503 removeIntentResult = main.TRUE
1504 # Remove intents
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001505 removeIntentResult = main.RESTs[ 0 ].removeAllIntents( )
kelvin-onlab44147802015-07-27 17:57:31 -07001506
1507 if removeIntentResult:
1508 main.log.info( itemName + ": There are no more intents remaining, " +
1509 "successfully removed all the intents." )
1510
1511 return removeIntentResult
1512
1513def checkFlowsCount( main ):
1514 """
1515 Check flows count in each node
1516 """
1517
1518 flowsCount = []
1519 main.log.info( itemName + ": Checking flows count in each ONOS node" )
1520 for i in range( main.numCtrls ):
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001521 flowsCount.append( len( json.loads( main.RESTs[ i ].flows() ) ) )
kelvin-onlab44147802015-07-27 17:57:31 -07001522
1523 if flowsCount:
1524 if all( flows==flowsCount[ 0 ] for flows in flowsCount ):
1525 main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
1526 " flows in all ONOS node" )
1527 else:
1528 for i in range( main.numCtrls ):
1529 main.log.debug( itemName + ": ONOS node " + str( i + 1 ) +
Jeremy2f190ca2016-01-29 15:23:57 -08001530 " has " + str( flowsCount[ i ] ) + " flows" )
kelvin-onlab44147802015-07-27 17:57:31 -07001531 else:
1532 main.log.error( "Checking flows count failed, check summary command" )
1533 return main.FALSE
1534
1535 return main.TRUE
1536
Jeremy2f190ca2016-01-29 15:23:57 -08001537def sendDiscoveryArp( main, hosts=None ):
1538 """
1539 Sends Discovery ARP packets from each host provided
1540 Defaults to each host in main.scapyHosts
1541 """
1542 # Send an arp ping from each host
1543 if not hosts:
1544 hosts = main.scapyHosts
1545 for host in hosts:
1546 pkt = 'Ether( src="{0}")/ARP( psrc="{1}")'.format( host.hostMac ,host.hostIp )
1547 # Send from the VLAN interface if there is one so ONOS discovers the VLAN correctly
1548 iface = None
1549 for interface in host.getIfList():
1550 if '.' in interface:
1551 main.log.debug( "Detected VLAN interface {0}. Sending ARP packet from {0}".format( interface ) )
1552 iface = interface
1553 break
1554 host.sendPacket( packet=pkt, iface=iface )
1555 main.log.info( "Sending ARP packet from {0}".format( host.name ) )
1556
1557def confirmHostDiscovery( main ):
1558 """
1559 Confirms that all ONOS nodes have discovered all scapy hosts
1560 """
1561 import collections
1562 scapyHostCount = len( main.scapyHosts )
1563 hosts = main.topo.getAllHosts( main ) # Get host data from each ONOS node
1564 hostFails = [] # Reset for each failed attempt
1565
1566 # Check for matching hosts on each node
1567 scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
1568 for controller in range( main.numCtrls ):
1569 controllerStr = str( controller + 1 ) # ONOS node number
1570 # Compare Hosts
1571 # Load hosts data for controller node
Jeremydd9bda62016-04-18 12:02:32 -07001572 try:
1573 if hosts[ controller ]:
1574 main.log.info( "Hosts discovered" )
Jeremy2f190ca2016-01-29 15:23:57 -08001575 else:
Jeremydd9bda62016-04-18 12:02:32 -07001576 main.log.error( "Problem discovering hosts" )
1577 if hosts[ controller ] and "Error" not in hosts[ controller ]:
1578 try:
1579 hostData = json.loads( hosts[ controller ] )
1580 except ( TypeError, ValueError ):
1581 main.log.error( "Could not load json:" + str( hosts[ controller ] ) )
Jeremy2f190ca2016-01-29 15:23:57 -08001582 hostFails.append( controllerStr )
Jeremydd9bda62016-04-18 12:02:32 -07001583 else:
1584 onosHostIPs = [ x.get( "ipAddresses" )[ 0 ]
1585 for x in hostData
1586 if len( x.get( "ipAddresses" ) ) > 0 ]
1587 if not set( collections.Counter( scapyHostIPs ) ).issubset( set ( collections.Counter( onosHostIPs ) ) ):
1588 main.log.warn( "Controller {0} only sees nodes with {1} IPs. It should see all of the following: {2}".format( controllerStr, onosHostIPs, scapyHostIPs ) )
1589 hostFails.append( controllerStr )
1590 else:
1591 main.log.error( "Hosts returned nothing or an error." )
1592 hostFails.append( controllerStr )
1593 except IndexError:
1594 main.log.error( "Hosts returned nothing, Failed to discover hosts." )
1595 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -08001596
1597 if hostFails:
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001598 main.log.error( "List of failed ONOS Nodes:" + ', '.join( map( str, hostFails ) ) )
Jeremy2f190ca2016-01-29 15:23:57 -08001599 return main.FALSE
1600 else:
1601 return main.TRUE
1602
1603def populateHostData( main ):
1604 """
1605 Populates hostsData
1606 """
1607 import json
1608 try:
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001609 hostsJson = json.loads( main.RESTs[ 0 ].hosts() )
Jeremy2f190ca2016-01-29 15:23:57 -08001610 hosts = main.Mininet1.getHosts().keys()
1611 # TODO: Make better use of new getHosts function
1612 for host in hosts:
1613 main.hostsData[ host ] = {}
1614 main.hostsData[ host ][ 'mac' ] = \
1615 main.Mininet1.getMacAddress( host ).upper()
1616 for hostj in hostsJson:
1617 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
1618 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
1619 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
1620 main.hostsData[ host ][ 'location' ] = \
1621 hostj[ 'location' ][ 'elementId' ] + '/' + \
1622 hostj[ 'location' ][ 'port' ]
1623 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
1624 return main.TRUE
Jeremydd9bda62016-04-18 12:02:32 -07001625 except ValueError:
1626 main.log.error( "ValueError while populating hostsData" )
1627 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -08001628 except KeyError:
1629 main.log.error( "KeyError while populating hostsData")
1630 return main.FALSE
Jeremydd9bda62016-04-18 12:02:32 -07001631 except IndexError:
1632 main.log.error( "IndexError while populating hostsData" )
1633 return main.FALSE
1634 except TypeError:
1635 main.log.error( "TypeError while populating hostsData" )
1636 return main.FALSE
Jeremy2f190ca2016-01-29 15:23:57 -08001637
Jeremy Songsterae2dd452016-05-17 16:44:35 -07001638def scapyCheckConnection( main, senders, recipients, vlanId=None, useTCP=False, packet=None, packetFilter=None, expectFailure=False ):
Jeremy2f190ca2016-01-29 15:23:57 -08001639 """
1640 Checks the connectivity between all given sender hosts and all given recipient hosts
1641 Packet may be specified. Defaults to Ether/IP packet
1642 Packet Filter may be specified. Defaults to Ether/IP from current sender MAC
1643 Todo: Optional packet and packet filter attributes for sender and recipients
1644 Expect Failure when the sender and recipient are not supposed to have connectivity
1645 Timeout of 1 second, returns main.TRUE if the filter is not triggered and kills the filter
1646
1647 """
1648 connectionsFunctional = main.TRUE
1649
1650 if not packetFilter:
1651 packetFilter = 'ether host {}'
Jeremy Songsterae2dd452016-05-17 16:44:35 -07001652 if useTCP:
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001653 packetFilter += ' ip proto \\tcp tcp port {}'.format( main.params[ 'SDNIP' ][ 'dstPort' ] )
Jeremy2f190ca2016-01-29 15:23:57 -08001654 if expectFailure:
1655 timeout = 1
1656 else:
1657 timeout = 10
1658
1659 for sender in senders:
1660 try:
1661 senderComp = getattr( main, sender )
1662 except AttributeError:
1663 main.log.error( "main has no attribute {}".format( sender ) )
1664 connectionsFunctional = main.FALSE
1665 continue
1666
1667 for recipient in recipients:
1668 # Do not send packets to self since recipient CLI will already be busy
1669 if recipient == sender:
1670 continue
1671 try:
1672 recipientComp = getattr( main, recipient )
1673 except AttributeError:
1674 main.log.error( "main has no attribute {}".format( recipient ) )
1675 connectionsFunctional = main.FALSE
1676 continue
1677
Jeremy Songsterae2dd452016-05-17 16:44:35 -07001678 if vlanId:
1679 recipientComp.startFilter( pktFilter = ( "vlan {}".format( vlanId ) + " && " + packetFilter.format( senderComp.hostMac ) ) )
1680 else:
1681 recipientComp.startFilter( pktFilter = packetFilter.format( senderComp.hostMac ) )
Jeremy2f190ca2016-01-29 15:23:57 -08001682
1683 if not packet:
Jeremy Songsterae2dd452016-05-17 16:44:35 -07001684 if vlanId:
1685 pkt = 'Ether( src="{0}", dst="{2}" )/Dot1Q(vlan={4})/IP( src="{1}", dst="{3}" )'.format(
1686 senderComp.hostMac,
1687 senderComp.hostIp,
1688 recipientComp.hostMac,
1689 recipientComp.hostIp,
1690 vlanId )
1691 else:
1692 pkt = 'Ether( src="{0}", dst="{2}" )/IP( src="{1}", dst="{3}" )'.format(
1693 senderComp.hostMac,
1694 senderComp.hostIp,
1695 recipientComp.hostMac,
1696 recipientComp.hostIp )
Jeremy2f190ca2016-01-29 15:23:57 -08001697 else:
1698 pkt = packet
Jeremy Songsterae2dd452016-05-17 16:44:35 -07001699 if vlanId:
1700 senderComp.sendPacket( iface=( "{0}-eth0.{1}".format( sender, vlanId ) ), packet = pkt )
1701 else:
1702 senderComp.sendPacket( packet = pkt )
Jeremy2f190ca2016-01-29 15:23:57 -08001703
1704 if recipientComp.checkFilter( timeout ):
1705 if expectFailure:
1706 main.log.error( "Packet from {0} successfully received by {1} when it should not have been".format( sender , recipient ) )
1707 connectionsFunctional = main.FALSE
1708 else:
1709 main.log.info( "Packet from {0} successfully received by {1}".format( sender , recipient ) )
1710 else:
1711 recipientComp.killFilter()
1712 if expectFailure:
1713 main.log.info( "As expected, packet from {0} was not received by {1}".format( sender , recipient ) )
1714 else:
1715 main.log.error( "Packet from {0} was not received by {1}".format( sender , recipient ) )
1716 connectionsFunctional = main.FALSE
1717
1718 return connectionsFunctional
1719
Jeremye1ea0602016-02-08 16:35:05 -08001720def checkLeaderChange( leaders1, leaders2 ):
1721 """
1722 Checks for a change in intent partition leadership.
1723
1724 Takes the output of leaders -c in json string format before and after
1725 a potential change as input
1726
1727 Returns main.TRUE if no mismatches are detected
1728 Returns main.FALSE if there is a mismatch or on error loading the input
1729 """
1730 try:
1731 leaders1 = json.loads( leaders1 )
1732 leaders2 = json.loads( leaders2 )
1733 except ( AttributeError, TypeError):
1734 main.log.exception( self.name + ": Object not as expected" )
1735 return main.FALSE
1736 except Exception:
1737 main.log.exception( self.name + ": Uncaught exception!" )
1738 main.cleanup()
1739 main.exit()
1740 main.log.info( "Checking Intent Paritions for Change in Leadership" )
1741 mismatch = False
1742 for dict1 in leaders1:
1743 if "intent" in dict1.get( "topic", [] ):
1744 for dict2 in leaders2:
1745 if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
1746 dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
1747 mismatch = True
1748 main.log.error( "{0} changed leader from {1} to {2}".\
1749 format( dict1.get( "topic", "no-topic" ),\
1750 dict1.get( "leader", "no-leader" ),\
1751 dict2.get( "leader", "no-leader" ) ) )
1752 if mismatch:
1753 return main.FALSE
1754 else:
1755 return main.TRUE
1756
1757
Jeremy2f190ca2016-01-29 15:23:57 -08001758def report( main ):
1759 """
1760 Report errors/warnings/exceptions
1761 """
1762 main.ONOSbench.logReport( main.ONOSip[ 0 ],
1763 [ "INFO",
1764 "FOLLOWER",
1765 "WARN",
1766 "flow",
1767 "ERROR",
1768 "Except" ],
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001769 "s" )
Jeremy2f190ca2016-01-29 15:23:57 -08001770
1771 main.log.info( "ERROR report: \n" )
1772 for i in range( main.numCtrls ):
1773 main.ONOSbench.logReport( main.ONOSip[ i ],
1774 [ "ERROR" ],
1775 "d" )
1776
1777 main.log.info( "EXCEPTIONS report: \n" )
1778 for i in range( main.numCtrls ):
1779 main.ONOSbench.logReport( main.ONOSip[ i ],
1780 [ "Except" ],
1781 "d" )
1782
1783 main.log.info( "WARNING report: \n" )
1784 for i in range( main.numCtrls ):
1785 main.ONOSbench.logReport( main.ONOSip[ i ],
1786 [ "WARN" ],
1787 "d" )
Jeremy Songster306ed7a2016-07-19 10:59:07 -07001788
1789def flowDuration( main ):
1790 """
1791 Check age of flows to see if flows are being overwritten
1792 """
1793 import time
1794 main.log.info( "Getting current flow durations" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001795 flowsJson1 = main.RESTs[ 0 ].flows()
Jeremy Songster306ed7a2016-07-19 10:59:07 -07001796 try:
1797 flowsJson1 = json.loads( flowsJson1 )
1798 except ValueError:
1799 main.log.error( "Unable to read flows" )
1800 return main.FALSE
1801 flowLife = []
1802 waitFlowLife = []
1803 for flow in flowsJson1:
1804 if flow[ 'appId' ] == "org.onosproject.net.intent":
1805 flowLife.append( flow[ 'life' ] )
1806 main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
1807 time.sleep( main.flowDurationSleep )
1808 main.log.info( "Getting new flow durations" )
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001809 flowsJson2 = main.RESTs[ 0 ].flows()
Jeremy Songster306ed7a2016-07-19 10:59:07 -07001810 try:
1811 flowsJson2 = json.loads( flowsJson2 )
1812 except ValueError:
1813 main.log.error( "Unable to read flows" )
1814 return main.FALSE
1815 for flow in flowsJson2:
1816 if flow[ 'appId' ] == "org.onosproject.net.intent":
1817 waitFlowLife.append( flow[ 'life' ] )
1818 main.log.info( "Determining whether flows where overwritten" )
1819 if len( flowLife ) == len( waitFlowLife ):
Jeremy Songstere7f3b342016-08-17 14:56:49 -07001820 for i in range( len( flowLife ) ):
Jeremy Songster306ed7a2016-07-19 10:59:07 -07001821 if waitFlowLife[ i ] - flowLife[ i ] < main.flowDurationSleep:
1822 return main.FALSE
1823 else:
1824 return main.FALSE
1825 return main.TRUE