blob: b73e9aa38907b00c8082a1941645fa4ad7a66207 [file] [log] [blame]
kelvin-onlabd48a68c2015-07-13 16:01:36 -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
9
10def __init__( self ):
11 self.default = ''
12
13def hostIntent( main,
14 name,
15 host1,
16 host2,
17 onosNode=0,
18 host1Id="",
19 host2Id="",
20 mac1="",
21 mac2="",
22 vlan1="-1",
23 vlan2="-1",
24 sw1="",
25 sw2="",
26 expectedLink=0 ):
27 """
28 Description:
29 Verify add-host-intent
30 Steps:
31 - Discover hosts
32 - Add host intents
33 - Check intents
34 - Verify flows
35 - Ping hosts
36 - Reroute
37 - Link down
38 - Verify flows
39 - Check topology
40 - Ping hosts
41 - Link up
42 - Verify flows
43 - Check topology
44 - Ping hosts
45 - Remove intents
46 Required:
47 name - Type of host intent to add eg. IPV4 | VLAN | Dualstack
48 host1 - Name of first host
49 host2 - Name of second host
50 Optional:
kelvin-onlabb769f562015-07-15 17:05:10 -070051 onosNode - ONOS node to install the intents in main.CLIs[ ]
52 0 by default so that it will always use the first
53 ONOS node
kelvin-onlabd48a68c2015-07-13 16:01:36 -070054 host1Id - ONOS id of the first host eg. 00:00:00:00:00:01/-1
55 host2Id - ONOS id of the second host
56 mac1 - Mac address of first host
57 mac2 - Mac address of the second host
58 vlan1 - Vlan tag of first host, defaults to -1
59 vlan2 - Vlan tag of second host, defaults to -1
60 sw1 - First switch to bring down & up for rerouting purpose
61 sw2 - Second switch to bring down & up for rerouting purpose
62 expectedLink - Expected link when the switches are down, it should
63 be two links lower than the links before the two
64 switches are down
kelvin-onlab6dea6e62015-07-23 13:07:26 -070065 Return:
66 Returns main.TRUE if all verification passed, otherwise return
67 main.FALSE; returns main.FALSE if there is a key error
kelvin-onlabd48a68c2015-07-13 16:01:36 -070068 """
69
70 # Assert variables
71 assert main, "There is no main variable"
72 assert name, "variable name is empty"
73 assert host1 and host2, "You must specify hosts"
74
75 global itemName
76 itemName = name
77 h1Id = host1Id
78 h2Id = host2Id
79 h1Mac = mac1
80 h2Mac = mac2
81 vlan1 = vlan1
82 vlan2 = vlan2
83 hostNames = [ host1 , host2 ]
84 intentsId = []
85 stepResult = main.TRUE
86 pingResult = main.TRUE
87 intentResult = main.TRUE
88 removeIntentResult = main.TRUE
89 flowResult = main.TRUE
90 topoResult = main.TRUE
91 linkDownResult = main.TRUE
92 linkUpResult = main.TRUE
93 onosNode = int( onosNode )
94
kelvin-onlab6dea6e62015-07-23 13:07:26 -070095 try:
96 if main.hostsData:
97 if not h1Mac:
98 h1Mac = main.hostsData[ host1 ][ 'mac' ]
99 if not h2Mac:
100 h2Mac = main.hostsData[ host2 ][ 'mac' ]
101 if main.hostsData[ host1 ].get( 'vlan' ):
102 vlan1 = main.hostsData[ host1 ][ 'vlan' ]
103 if main.hostsData[ host1 ].get( 'vlan' ):
104 vlan2 = main.hostsData[ host2 ][ 'vlan' ]
105 if not h1Id:
106 h1Id = main.hostsData[ host1 ][ 'id' ]
107 if not h2Id:
108 h2Id = main.hostsData[ host2 ][ 'id' ]
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700109
kelvin-onlab6dea6e62015-07-23 13:07:26 -0700110 assert h1Id and h2Id, "You must specify host IDs"
111 if not ( h1Id and h2Id ):
112 main.log.info( "There are no host IDs" )
113 return main.FALSE
114
kelvin-onlab6dea6e62015-07-23 13:07:26 -0700115 except KeyError:
116 main.log.error( itemName + ": Key error Exception" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700117 return main.FALSE
118
kelvin-onlab0ad05d12015-07-23 14:21:15 -0700119 # Discover hosts using arping incase pingall discovery failed
120 main.log.info( itemName + ": Discover host using arping" )
121 main.Mininet1.arping( host=host1 )
122 main.Mininet1.arping( host=host2 )
123 host1 = main.CLIs[ 0 ].getHost( mac=h1Mac )
124 host2 = main.CLIs[ 0 ].getHost( mac=h2Mac )
125
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700126 # Check flows count in each node
127 checkFlowsCount( main )
128
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700129 # Adding host intents
130 main.log.info( itemName + ": Adding host intents" )
131 intent1 = main.CLIs[ onosNode ].addHostIntent( hostIdOne=h1Id,
kelvin-onlab6dea6e62015-07-23 13:07:26 -0700132 hostIdTwo=h2Id )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700133 intentsId.append( intent1 )
134
135 # Check intents state
136 time.sleep( main.checkIntentSleep )
137 intentResult = checkIntentState( main, intentsId )
138 checkFlowsCount( main )
139
140 # Check intents state again if first check fails...
141 if not intentResult:
142 intentResult = checkIntentState( main, intentsId )
143
144 # Check flows count in each node
145 checkFlowsCount( main )
146 # Verify flows
147 checkFlowsState( main )
148
149 # Ping hosts
150 firstPingResult = pingallHosts( main, hostNames )
151 if not firstPingResult:
152 main.log.debug( "First ping failed, there must be" +
153 " something wrong with ONOS performance" )
154
155 # Ping hosts again...
156 pingResult = pingResult and pingallHosts( main, hostNames )
157
158 # Test rerouting if these variables exist
159 if sw1 and sw2 and expectedLink:
160 # link down
161 linkDownResult = link( main, sw1, sw2, "down" )
162 intentResult = intentResult and checkIntentState( main, intentsId )
163
164 # Check flows count in each node
165 checkFlowsCount( main )
166 # Verify flows
167 checkFlowsState( main )
168
169 # Check OnosTopology
170 topoResult = checkTopology( main, expectedLink )
171
172 # Ping hosts
173 pingResult = pingResult and pingallHosts( main, hostNames )
174
175 intentResult = checkIntentState( main, intentsId )
176
177 # Checks ONOS state in link down
178 if linkDownResult and topoResult and pingResult and intentResult:
179 main.log.info( itemName + ": Successfully brought link down" )
180 else:
181 main.log.error( itemName + ": Failed to bring link down" )
182
183 # link up
184 linkUpResult = link( main, sw1, sw2, "up" )
185 time.sleep( main.rerouteSleep )
186
187 # Check flows count in each node
188 checkFlowsCount( main )
189 # Verify flows
190 checkFlowsState( main )
191
192 # Check OnosTopology
193 topoResult = checkTopology( main, main.numLinks )
194
195 # Ping hosts
196 pingResult = pingResult and pingallHosts( main, hostNames )
197
198 intentResult = checkIntentState( main, intentsId )
199
200 # Checks ONOS state in link up
201 if linkUpResult and topoResult and pingResult and intentResult:
202 main.log.info( itemName + ": Successfully brought link back up" )
203 else:
204 main.log.error( itemName + ": Failed to bring link back up" )
205
206 # Remove all intents
207 removeIntentResult = removeAllIntents( main, intentsId )
208
209 stepResult = pingResult and linkDownResult and linkUpResult \
210 and intentResult and removeIntentResult
211
212 return stepResult
213
214def pointIntent( main,
215 name,
216 host1,
217 host2,
218 onosNode=0,
219 deviceId1="",
220 deviceId2="",
221 port1="",
222 port2="",
223 ethType="",
224 mac1="",
225 mac2="",
226 bandwidth="",
227 lambdaAlloc=False,
228 ipProto="",
229 ip1="",
230 ip2="",
231 tcp1="",
232 tcp2="",
233 sw1="",
234 sw2="",
235 expectedLink=0 ):
236
237 """
238 Description:
239 Verify add-point-intent
240 Steps:
241 - Get device ids | ports
242 - Add point intents
243 - Check intents
244 - Verify flows
245 - Ping hosts
246 - Reroute
247 - Link down
248 - Verify flows
249 - Check topology
250 - Ping hosts
251 - Link up
252 - Verify flows
253 - Check topology
254 - Ping hosts
255 - Remove intents
256 Required:
257 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
258 host1 - Name of first host
259 host2 - Name of second host
260 Optional:
kelvin-onlabb769f562015-07-15 17:05:10 -0700261 onosNode - ONOS node to install the intents in main.CLIs[ ]
262 0 by default so that it will always use the first
263 ONOS node
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700264 deviceId1 - ONOS device id of the first switch, the same as the
265 location of the first host eg. of:0000000000000001/1,
266 located at device 1 port 1
267 deviceId2 - ONOS device id of the second switch
268 port1 - The port number where the first host is attached
269 port2 - The port number where the second host is attached
270 ethType - Ethernet type eg. IPV4, IPV6
271 mac1 - Mac address of first host
272 mac2 - Mac address of the second host
273 bandwidth - Bandwidth capacity
274 lambdaAlloc - Allocate lambda, defaults to False
275 ipProto - IP protocol
276 ip1 - IP address of first host
277 ip2 - IP address of second host
278 tcp1 - TCP port of first host
279 tcp2 - TCP port of second host
280 sw1 - First switch to bring down & up for rerouting purpose
281 sw2 - Second switch to bring down & up for rerouting purpose
282 expectedLink - Expected link when the switches are down, it should
283 be two links lower than the links before the two
284 switches are down
285 """
286
287 assert main, "There is no main variable"
288 assert name, "variable name is empty"
289 assert host1 and host2, "You must specify hosts"
290
291 global itemName
292 itemName = name
293 host1 = host1
294 host2 = host2
295 hostNames = [ host1, host2 ]
296 intentsId = []
297
298 pingResult = main.TRUE
299 intentResult = main.TRUE
300 removeIntentResult = main.TRUE
301 flowResult = main.TRUE
302 topoResult = main.TRUE
303 linkDownResult = main.TRUE
304 linkUpResult = main.TRUE
305 onosNode = int( onosNode )
306
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700307 # Adding bidirectional point intents
308 main.log.info( itemName + ": Adding point intents" )
309 intent1 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
310 egressDevice=deviceId2,
311 portIngress=port1,
312 portEgress=port2,
313 ethType=ethType,
314 ethSrc=mac1,
315 ethDst=mac2,
316 bandwidth=bandwidth,
317 lambdaAlloc=lambdaAlloc,
318 ipProto=ipProto,
319 ipSrc=ip1,
320 ipDst=ip2,
321 tcpSrc=tcp1,
322 tcpDst=tcp2 )
323
324 intentsId.append( intent1 )
325 intent2 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
326 egressDevice=deviceId1,
327 portIngress=port2,
328 portEgress=port1,
329 ethType=ethType,
330 ethSrc=mac2,
331 ethDst=mac1,
332 bandwidth=bandwidth,
333 lambdaAlloc=lambdaAlloc,
334 ipProto=ipProto,
335 ipSrc=ip2,
336 ipDst=ip1,
337 tcpSrc=tcp2,
338 tcpDst=tcp1 )
339 intentsId.append( intent2 )
340
341 # Check intents state
342 time.sleep( main.checkIntentSleep )
343 intentResult = checkIntentState( main, intentsId )
344 # Check flows count in each node
345 checkFlowsCount( main )
346
347 # Check intents state again if first check fails...
348 if not intentResult:
349 intentResult = checkIntentState( main, intentsId )
350
351 # Check flows count in each node
352 checkFlowsCount( main )
353 # Verify flows
354 checkFlowsState( main )
355
356 # Ping hosts
357 firstPingResult = pingallHosts( main, hostNames )
358 if not firstPingResult:
359 main.log.debug( "First ping failed, there must be" +
360 " something wrong with ONOS performance" )
361
362 # Ping hosts again...
363 pingResult = pingResult and pingallHosts( main, hostNames )
364
365 # Test rerouting if these variables exist
366 if sw1 and sw2 and expectedLink:
367 # link down
368 linkDownResult = link( main, sw1, sw2, "down" )
369 intentResult = intentResult and checkIntentState( main, intentsId )
370
371 # Check flows count in each node
372 checkFlowsCount( main )
373 # Verify flows
374 checkFlowsState( main )
375
376 # Check OnosTopology
377 topoResult = checkTopology( main, expectedLink )
378
379 # Ping hosts
380 pingResult = pingResult and pingallHosts( main, hostNames )
381
382 intentResult = checkIntentState( main, intentsId )
383
384 # Checks ONOS state in link down
385 if linkDownResult and topoResult and pingResult and intentResult:
386 main.log.info( itemName + ": Successfully brought link down" )
387 else:
388 main.log.error( itemName + ": Failed to bring link down" )
389
390 # link up
391 linkUpResult = link( main, sw1, sw2, "up" )
392 time.sleep( main.rerouteSleep )
393
394 # Check flows count in each node
395 checkFlowsCount( main )
396 # Verify flows
397 checkFlowsState( main )
398
399 # Check OnosTopology
400 topoResult = checkTopology( main, main.numLinks )
401
402 # Ping hosts
403 pingResult = pingResult and pingallHosts( main, hostNames )
404
405 intentResult = checkIntentState( main, intentsId )
406
407 # Checks ONOS state in link up
408 if linkUpResult and topoResult and pingResult and intentResult:
409 main.log.info( itemName + ": Successfully brought link back up" )
410 else:
411 main.log.error( itemName + ": Failed to bring link back up" )
412
413 # Remove all intents
414 removeIntentResult = removeAllIntents( main, intentsId )
415
416 stepResult = pingResult and linkDownResult and linkUpResult \
417 and intentResult and removeIntentResult
418
419 return stepResult
420
421def singleToMultiIntent( main,
422 name,
423 hostNames,
424 onosNode=0,
425 devices="",
426 ports=None,
427 ethType="",
428 macs=None,
429 bandwidth="",
430 lambdaAlloc=False,
431 ipProto="",
432 ipAddresses="",
433 tcp="",
434 sw1="",
435 sw2="",
436 expectedLink=0 ):
437 """
438 Verify Single to Multi Point intents
439 NOTE:If main.hostsData is not defined, variables data should be passed in the
440 same order index wise. All devices in the list should have the same
441 format, either all the devices have its port or it doesn't.
442 eg. hostName = [ 'h1', 'h2' ,.. ]
443 devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
444 ports = [ '1', '1', ..]
445 ...
446 Description:
447 Verify add-single-to-multi-intent iterates through the list of given
448 host | devices and add intents
449 Steps:
450 - Get device ids | ports
451 - Add single to multi point intents
452 - Check intents
453 - Verify flows
454 - Ping hosts
455 - Reroute
456 - Link down
457 - Verify flows
458 - Check topology
459 - Ping hosts
460 - Link up
461 - Verify flows
462 - Check topology
463 - Ping hosts
464 - Remove intents
465 Required:
466 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
467 hostNames - List of host names
468 Optional:
kelvin-onlabb769f562015-07-15 17:05:10 -0700469 onosNode - ONOS node to install the intents in main.CLIs[ ]
470 0 by default so that it will always use the first
471 ONOS node
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700472 devices - List of device ids in the same order as the hosts
473 in hostNames
474 ports - List of port numbers in the same order as the device in
475 devices
476 ethType - Ethernet type eg. IPV4, IPV6
477 macs - List of hosts mac address in the same order as the hosts in
478 hostNames
479 bandwidth - Bandwidth capacity
480 lambdaAlloc - Allocate lambda, defaults to False
481 ipProto - IP protocol
482 ipAddresses - IP addresses of host in the same order as the hosts in
483 hostNames
484 tcp - TCP ports in the same order as the hosts in hostNames
485 sw1 - First switch to bring down & up for rerouting purpose
486 sw2 - Second switch to bring down & up for rerouting purpose
487 expectedLink - Expected link when the switches are down, it should
488 be two links lower than the links before the two
489 switches are down
490 """
491
492 assert main, "There is no main variable"
493 assert hostNames, "You must specify hosts"
494 assert devices or main.hostsData, "You must specify devices"
495
496 global itemName
497 itemName = name
498 tempHostsData = {}
499 intentsId = []
500 onosNode = int( onosNode )
501
502 macsDict = {}
503 ipDict = {}
504 if hostNames and devices:
505 if len( hostNames ) != len( devices ):
506 main.log.debug( "hosts and devices does not have the same length" )
507 #print "len hostNames = ", len( hostNames )
508 #print "len devices = ", len( devices )
509 return main.FALSE
510 if ports:
511 if len( ports ) != len( devices ):
512 main.log.error( "Ports and devices does " +
513 "not have the same length" )
514 #print "len devices = ", len( devices )
515 #print "len ports = ", len( ports )
516 return main.FALSE
517 else:
518 main.log.info( "Device Ports are not specified" )
519 if macs:
520 for i in range( len( devices ) ):
521 macsDict[ devices[ i ] ] = macs[ i ]
522
523 elif hostNames and not devices and main.hostsData:
524 devices = []
525 main.log.info( "singleToMultiIntent function is using main.hostsData" )
526 for host in hostNames:
527 devices.append( main.hostsData.get( host ).get( 'location' ) )
528 macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
529 main.hostsData.get( host ).get( 'mac' )
530 ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
531 main.hostsData.get( host ).get( 'ipAddresses' )
532 #print main.hostsData
533
534 #print 'host names = ', hostNames
535 #print 'devices = ', devices
536 #print "macsDict = ", macsDict
537
538 pingResult = main.TRUE
539 intentResult = main.TRUE
540 removeIntentResult = main.TRUE
541 flowResult = main.TRUE
542 topoResult = main.TRUE
543 linkDownResult = main.TRUE
544 linkUpResult = main.TRUE
545
546 devicesCopy = copy.copy( devices )
547 if ports:
548 portsCopy = copy.copy( ports )
549 main.log.info( itemName + ": Adding single point to multi point intents" )
550
551 # Check flows count in each node
552 checkFlowsCount( main )
553
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700554 # Adding bidirectional point intents
555 for i in range( len( devices ) ):
556 ingressDevice = devicesCopy[ i ]
557 egressDeviceList = copy.copy( devicesCopy )
558 egressDeviceList.remove( ingressDevice )
559 if ports:
560 portIngress = portsCopy[ i ]
561 portEgressList = copy.copy( portsCopy )
562 del portEgressList[ i ]
563 else:
564 portIngress = ""
565 portEgressList = None
566 if not macsDict:
567 srcMac = ""
568 else:
569 srcMac = macsDict[ ingressDevice ]
570 if srcMac == None:
571 main.log.debug( "There is no MAC in device - " + ingressDevice )
572 srcMac = ""
573
574 intentsId.append(
575 main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
576 ingressDevice=ingressDevice,
577 egressDeviceList=egressDeviceList,
578 portIngress=portIngress,
579 portEgressList=portEgressList,
580 ethType=ethType,
581 ethSrc=srcMac,
582 bandwidth=bandwidth,
583 lambdaAlloc=lambdaAlloc,
584 ipProto=ipProto,
585 ipSrc="",
586 ipDst="",
587 tcpSrc="",
588 tcpDst="" ) )
589
590 # Wait some time for the flow to go through when using multi instance
591 pingResult = pingallHosts( main, hostNames )
592
593 # Check intents state
594 time.sleep( main.checkIntentSleep )
595 intentResult = checkIntentState( main, intentsId )
596
597 # Check intents state again if first check fails...
598 if not intentResult:
599 intentResult = checkIntentState( main, intentsId )
600
601 # Check flows count in each node
602 checkFlowsCount( main )
603 # Verify flows
604 checkFlowsState( main )
605
606 pingResult = pingResult and pingallHosts( main, hostNames )
607
608 # Test rerouting if these variables exist
609 if sw1 and sw2 and expectedLink:
610 # link down
611 linkDownResult = link( main, sw1, sw2, "down" )
612 intentResult = intentResult and checkIntentState( main, intentsId )
613
614 # Check flows count in each node
615 checkFlowsCount( main )
616 # Verify flows
617 checkFlowsState( main )
618
619 # Check OnosTopology
620 topoResult = checkTopology( main, expectedLink )
621
622 # Ping hosts
623 pingResult = pingResult and pingallHosts( main, hostNames )
624
625 intentResult = checkIntentState( main, intentsId )
626
627 # Checks ONOS state in link down
628 if linkDownResult and topoResult and pingResult and intentResult:
629 main.log.info( itemName + ": Successfully brought link down" )
630 else:
631 main.log.error( itemName + ": Failed to bring link down" )
632
633 # link up
634 linkUpResult = link( main, sw1, sw2, "up" )
635 time.sleep( main.rerouteSleep )
636
637 # Check flows count in each node
638 checkFlowsCount( main )
639 # Verify flows
640 checkFlowsState( main )
641
642 # Check OnosTopology
643 topoResult = checkTopology( main, main.numLinks )
644
645 # Ping hosts
646 pingResult = pingResult and pingallHosts( main, hostNames )
647
648 intentResult = checkIntentState( main, intentsId )
649
650 # Checks ONOS state in link up
651 if linkUpResult and topoResult and pingResult and intentResult:
652 main.log.info( itemName + ": Successfully brought link back up" )
653 else:
654 main.log.error( itemName + ": Failed to bring link back up" )
655
656 # Remove all intents
657 removeIntentResult = removeAllIntents( main, intentsId )
658
659 stepResult = pingResult and linkDownResult and linkUpResult \
660 and intentResult and removeIntentResult
661
662 return stepResult
663
664def multiToSingleIntent( main,
665 name,
666 hostNames,
667 onosNode=0,
668 devices="",
669 ports=None,
670 ethType="",
671 macs=None,
672 bandwidth="",
673 lambdaAlloc=False,
674 ipProto="",
675 ipAddresses="",
676 tcp="",
677 sw1="",
678 sw2="",
679 expectedLink=0 ):
680 """
681 Verify Single to Multi Point intents
682 NOTE:If main.hostsData is not defined, variables data should be passed in the
683 same order index wise. All devices in the list should have the same
684 format, either all the devices have its port or it doesn't.
685 eg. hostName = [ 'h1', 'h2' ,.. ]
686 devices = [ 'of:0000000000000001', 'of:0000000000000002', ...]
687 ports = [ '1', '1', ..]
688 ...
689 Description:
690 Verify add-multi-to-single-intent
691 Steps:
692 - Get device ids | ports
693 - Add multi to single point intents
694 - Check intents
695 - Verify flows
696 - Ping hosts
697 - Reroute
698 - Link down
699 - Verify flows
700 - Check topology
701 - Ping hosts
702 - Link up
703 - Verify flows
704 - Check topology
705 - Ping hosts
706 - Remove intents
707 Required:
708 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
709 hostNames - List of host names
710 Optional:
kelvin-onlabb769f562015-07-15 17:05:10 -0700711 onosNode - ONOS node to install the intents in main.CLIs[ ]
712 0 by default so that it will always use the first
713 ONOS node
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700714 devices - List of device ids in the same order as the hosts
715 in hostNames
716 ports - List of port numbers in the same order as the device in
717 devices
718 ethType - Ethernet type eg. IPV4, IPV6
719 macs - List of hosts mac address in the same order as the hosts in
720 hostNames
721 bandwidth - Bandwidth capacity
722 lambdaAlloc - Allocate lambda, defaults to False
723 ipProto - IP protocol
724 ipAddresses - IP addresses of host in the same order as the hosts in
725 hostNames
726 tcp - TCP ports in the same order as the hosts in hostNames
727 sw1 - First switch to bring down & up for rerouting purpose
728 sw2 - Second switch to bring down & up for rerouting purpose
729 expectedLink - Expected link when the switches are down, it should
730 be two links lower than the links before the two
731 switches are down
732 """
733
734 assert main, "There is no main variable"
735 assert hostNames, "You must specify hosts"
736 assert devices or main.hostsData, "You must specify devices"
737
738 global itemName
739 itemName = name
740 tempHostsData = {}
741 intentsId = []
742 onosNode = int( onosNode )
743
744 macsDict = {}
745 ipDict = {}
746 if hostNames and devices:
747 if len( hostNames ) != len( devices ):
748 main.log.debug( "hosts and devices does not have the same length" )
749 #print "len hostNames = ", len( hostNames )
750 #print "len devices = ", len( devices )
751 return main.FALSE
752 if ports:
753 if len( ports ) != len( devices ):
754 main.log.error( "Ports and devices does " +
755 "not have the same length" )
756 #print "len devices = ", len( devices )
757 #print "len ports = ", len( ports )
758 return main.FALSE
759 else:
760 main.log.info( "Device Ports are not specified" )
761 if macs:
762 for i in range( len( devices ) ):
763 macsDict[ devices[ i ] ] = macs[ i ]
764 elif hostNames and not devices and main.hostsData:
765 devices = []
766 main.log.info( "multiToSingleIntent function is using main.hostsData" )
767 for host in hostNames:
768 devices.append( main.hostsData.get( host ).get( 'location' ) )
769 macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
770 main.hostsData.get( host ).get( 'mac' )
771 ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
772 main.hostsData.get( host ).get( 'ipAddresses' )
773 #print main.hostsData
774
775 #print 'host names = ', hostNames
776 #print 'devices = ', devices
777 #print "macsDict = ", macsDict
778
779 pingResult = main.TRUE
780 intentResult = main.TRUE
781 removeIntentResult = main.TRUE
782 flowResult = main.TRUE
783 topoResult = main.TRUE
784 linkDownResult = main.TRUE
785 linkUpResult = main.TRUE
786
787 devicesCopy = copy.copy( devices )
788 if ports:
789 portsCopy = copy.copy( ports )
790 main.log.info( itemName + ": Adding multi point to single point intents" )
791
792 # Check flows count in each node
793 checkFlowsCount( main )
794
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700795 # Adding bidirectional point intents
796 for i in range( len( devices ) ):
797 egressDevice = devicesCopy[ i ]
798 ingressDeviceList = copy.copy( devicesCopy )
799 ingressDeviceList.remove( egressDevice )
800 if ports:
801 portEgress = portsCopy[ i ]
802 portIngressList = copy.copy( portsCopy )
803 del portIngressList[ i ]
804 else:
805 portEgress = ""
806 portIngressList = None
807 if not macsDict:
808 dstMac = ""
809 else:
810 dstMac = macsDict[ egressDevice ]
811 if dstMac == None:
812 main.log.debug( "There is no MAC in device - " + egressDevice )
813 dstMac = ""
814
815 intentsId.append(
816 main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
817 ingressDeviceList=ingressDeviceList,
818 egressDevice=egressDevice,
819 portIngressList=portIngressList,
820 portEgress=portEgress,
821 ethType=ethType,
822 ethDst=dstMac,
823 bandwidth=bandwidth,
824 lambdaAlloc=lambdaAlloc,
825 ipProto=ipProto,
826 ipSrc="",
827 ipDst="",
828 tcpSrc="",
829 tcpDst="" ) )
830
831 pingResult = pingallHosts( main, hostNames )
832
833 # Check intents state
834 time.sleep( main.checkIntentSleep )
835 intentResult = checkIntentState( main, intentsId )
836
837 # Check intents state again if first check fails...
838 if not intentResult:
839 intentResult = checkIntentState( main, intentsId )
840
841 # Check flows count in each node
842 checkFlowsCount( main )
843 # Verify flows
844 checkFlowsState( main )
845
846 # Ping hosts
847 pingResult = pingResult and pingallHosts( main, hostNames )
848 # Ping hosts again...
849 pingResult = pingResult and pingallHosts( main, hostNames )
850
851 # Test rerouting if these variables exist
852 if sw1 and sw2 and expectedLink:
853 # link down
854 linkDownResult = link( main, sw1, sw2, "down" )
855 intentResult = intentResult and checkIntentState( main, intentsId )
856
857 # Check flows count in each node
858 checkFlowsCount( main )
859 # Verify flows
860 checkFlowsState( main )
861
862 # Check OnosTopology
863 topoResult = checkTopology( main, expectedLink )
864
865 # Ping hosts
866 pingResult = pingResult and pingallHosts( main, hostNames )
867
868 intentResult = checkIntentState( main, intentsId )
869
870 # Checks ONOS state in link down
871 if linkDownResult and topoResult and pingResult and intentResult:
872 main.log.info( itemName + ": Successfully brought link down" )
873 else:
874 main.log.error( itemName + ": Failed to bring link down" )
875
876 # link up
877 linkUpResult = link( main, sw1, sw2, "up" )
878 time.sleep( main.rerouteSleep )
879
880 # Check flows count in each node
881 checkFlowsCount( main )
882 # Verify flows
883 checkFlowsState( main )
884
885 # Check OnosTopology
886 topoResult = checkTopology( main, main.numLinks )
887
888 # Ping hosts
889 pingResult = pingResult and pingallHosts( main, hostNames )
890
891 intentResult = checkIntentState( main, intentsId )
892
893 # Checks ONOS state in link up
894 if linkUpResult and topoResult and pingResult and intentResult:
895 main.log.info( itemName + ": Successfully brought link back up" )
896 else:
897 main.log.error( itemName + ": Failed to bring link back up" )
898
899 # Remove all intents
900 removeIntentResult = removeAllIntents( main, intentsId )
901
902 stepResult = pingResult and linkDownResult and linkUpResult \
903 and intentResult and removeIntentResult
904
905 return stepResult
906
907def pingallHosts( main, hostList, pingType="ipv4" ):
908 # Ping all host in the hosts list variable
909 print "Pinging : ", hostList
910 pingResult = main.TRUE
911 pingResult = main.Mininet1.pingallHosts( hostList, pingType )
912 return pingResult
913
914def getHostsData( main ):
915 """
916 Use fwd app and pingall to discover all the hosts
917 """
918
919 activateResult = main.TRUE
920 appCheck = main.TRUE
921 getDataResult = main.TRUE
922 main.log.info( "Activating reactive forwarding app " )
923 activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
kelvin-onlab0ad05d12015-07-23 14:21:15 -0700924 time.sleep( main.fwdSleep )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700925
926 for i in range( main.numCtrls ):
927 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
928 if appCheck != main.TRUE:
929 main.log.warn( main.CLIs[ i ].apps() )
930 main.log.warn( main.CLIs[ i ].appIDs() )
931
932 pingResult = main.Mininet1.pingall( timeout = 600 )
933 hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
934 hosts = main.Mininet1.getHosts().keys()
935 # TODO: Make better use of new getHosts function
936 for host in hosts:
937 main.hostsData[ host ] = {}
938 main.hostsData[ host ][ 'mac' ] = \
939 main.Mininet1.getMacAddress( host ).upper()
940 for hostj in hostsJson:
941 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
942 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
943 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
944 main.hostsData[ host ][ 'location' ] = \
945 hostj[ 'location' ][ 'elementId' ] + '/' + \
946 hostj[ 'location' ][ 'port' ]
947 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
948
949 main.log.info( "Deactivating reactive forwarding app " )
950 deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
951 if activateResult and deactivateResult and main.hostsData:
952 main.log.info( "Successfully used fwd app to discover hosts " )
953 getDataResult = main.TRUE
954 else:
955 main.log.info( "Failed to use fwd app to discover hosts " )
956 getDataResult = main.FALSE
957
958 print main.hostsData
959
960 return getDataResult
961
962def checkTopology( main, expectedLink ):
963 statusResult = main.TRUE
964 # Check onos topology
965 main.log.info( itemName + ": Checking ONOS topology " )
966
967 for i in range( main.numCtrls ):
968 topologyResult = main.CLIs[ i ].topology()
969 statusResult = main.ONOSbench.checkStatus( topologyResult,
970 main.numSwitch,
971 expectedLink )\
972 and statusResult
973 if not statusResult:
974 main.log.error( itemName + ": Topology mismatch" )
975 else:
976 main.log.info( itemName + ": Topology match" )
977 return statusResult
978
979def checkIntentState( main, intentsId ):
980 """
981 This function will check intent state to make sure all the intents
982 are in INSTALLED state
983 """
984
985 intentResult = main.TRUE
986 results = []
987
988 main.log.info( itemName + ": Checking intents state" )
989 # First check of intents
990 for i in range( main.numCtrls ):
991 tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
992 results.append( tempResult )
993
994 expectedState = [ 'INSTALLED', 'INSTALLING' ]
995
996 if all( result == main.TRUE for result in results ):
997 main.log.info( itemName + ": Intents are installed correctly" )
998 else:
999 # Wait for at least 5 second before checking the intents again
1000 time.sleep( 5 )
1001 results = []
1002 # Second check of intents since some of the intents may be in
1003 # INSTALLING state, they should be in INSTALLED at this time
1004 for i in range( main.numCtrls ):
1005 tempResult = main.CLIs[ i ].checkIntentState(
1006 intentsId=intentsId )
1007 results.append( tempResult )
1008 if all( result == main.TRUE for result in results ):
1009 main.log.info( itemName + ": Intents are installed correctly" )
1010 else:
1011 main.log.error( itemName + ": Intents are NOT installed correctly" )
1012 intentResult = main.FALSE
1013
1014 return intentResult
1015
1016def checkFlowsState( main ):
1017
1018 main.log.info( itemName + ": Check flows state" )
1019 checkFlowsResult = main.CLIs[ 0 ].checkFlowsState()
1020 return checkFlowsResult
1021
1022def link( main, sw1, sw2, option):
1023
1024 # link down
1025 main.log.info( itemName + ": Bring link " + option + "between " +
1026 sw1 + " and " + sw2 )
1027 linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
1028 return linkResult
1029
1030def removeAllIntents( main, intentsId ):
1031 """
1032 Remove all intents in the intentsId
1033 """
1034
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001035 onosSummary = []
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001036 removeIntentResult = main.TRUE
1037 # Remove intents
1038 for intent in intentsId:
1039 main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
1040
1041 time.sleep( 5 )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001042
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001043 # If there is remianing intents then remove intents should fail
1044 for i in range( main.numCtrls ):
1045 onosSummary.append( json.loads( main.CLIs[ i ].summary() ) )
1046
1047 for summary in onosSummary:
1048 if summary.get( 'intents' ) != 0:
1049 main.log.warn( itemName + ": There are " +
1050 str( summary.get( 'intents' ) ) +
1051 " intents remaining in node " +
1052 str( summary.get( 'node' ) ) +
1053 ", failed to remove all the intents " )
1054 removeIntentResult = main.FALSE
1055
1056 if removeIntentResult:
1057 main.log.info( itemName + ": There are no more intents remaining, " +
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001058 "successfully removed all the intents." )
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001059
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001060 return removeIntentResult
1061
1062def checkFlowsCount( main ):
1063 """
1064 Check flows count in each node
1065 """
1066
1067 flowsCount = []
1068 main.log.info( itemName + ": Checking flows count in each ONOS node" )
1069 for i in range( main.numCtrls ):
1070 summaryResult = main.CLIs[ i ].summary()
1071 if not summaryResult:
1072 main.log.error( itemName + ": There is something wrong with " +
1073 "summary command" )
1074 return main.FALSE
1075 else:
1076 summaryJson = json.loads( summaryResult )
1077 flowsCount.append( summaryJson.get( 'flows' ) )
1078
1079 if flowsCount:
1080 if all( flows==flowsCount[ 0 ] for flows in flowsCount ):
1081 main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
1082 " flows in all ONOS node" )
1083 else:
1084 for i in range( main.numCtrls ):
1085 main.log.debug( itemName + ": ONOS node " + str( i ) + " has " +
kelvin-onlab6dea6e62015-07-23 13:07:26 -07001086 str( flowsCount[ i ] ) + " flows" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001087 else:
1088 main.log.error( "Checking flows count failed, check summary command" )
1089 return main.FALSE
1090
1091 return main.TRUE
1092
acsmarse6b410f2015-07-17 14:39:34 -07001093def checkLeaderChange( leaders1 , leaders2 ):
1094 """
1095 Checks for a change in intent partition leadership.
1096
1097 Takes the output of leaders -c in json string format before and after
1098 a potential change as input
1099
1100 Returns main.TRUE if no mismatches are detected
1101 Returns main.FALSE if there is a mismatch or on error loading the input
1102 """
1103 try:
1104 leaders1 = json.loads( leaders1 )
1105 leaders2 = json.loads( leaders2 )
1106 except ( AttributeError, TypeError):
1107 main.log.exception( self.name + ": Object not as expected" )
1108 return main.FALSE
1109 except Exception:
1110 main.log.exception( self.name + ": Uncaught exception!" )
1111 main.cleanup()
1112 main.exit()
1113 main.log.info( "Checking Intent Paritions for Change in Leadership" )
1114 mismatch = False
1115 for dict1 in leaders1:
1116 if "intent" in dict1.get( "topic", [] ):
1117 for dict2 in leaders2:
1118 if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
1119 dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
1120 mismatch = True
1121 main.log.error( "{0} changed leader from {1} to {2}".\
1122 format( dict1.get( "topic", "no-topic" ),\
1123 dict1.get( "leader", "no-leader" ),\
1124 dict2.get( "leader", "no-leader" ) ) )
1125 if mismatch:
1126 return main.FALSE
1127 else:
1128 return main.TRUE