blob: db9f0cf207169b17a862c7af299c12f06006c0b3 [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
115 # Discover hosts using arping
116 if not main.hostsData:
117 main.log.info( itemName + ": Discover host using arping" )
118 main.Mininet1.arping( host=host1 )
119 main.Mininet1.arping( host=host2 )
120 host1 = main.CLIs[ 0 ].getHost( mac=h1Mac )
121 host2 = main.CLIs[ 0 ].getHost( mac=h2Mac )
122 except KeyError:
123 main.log.error( itemName + ": Key error Exception" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700124 return main.FALSE
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" )
924
925 for i in range( main.numCtrls ):
926 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
927 if appCheck != main.TRUE:
928 main.log.warn( main.CLIs[ i ].apps() )
929 main.log.warn( main.CLIs[ i ].appIDs() )
930
931 pingResult = main.Mininet1.pingall( timeout = 600 )
932 hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
933 hosts = main.Mininet1.getHosts().keys()
934 # TODO: Make better use of new getHosts function
935 for host in hosts:
936 main.hostsData[ host ] = {}
937 main.hostsData[ host ][ 'mac' ] = \
938 main.Mininet1.getMacAddress( host ).upper()
939 for hostj in hostsJson:
940 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
941 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
942 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
943 main.hostsData[ host ][ 'location' ] = \
944 hostj[ 'location' ][ 'elementId' ] + '/' + \
945 hostj[ 'location' ][ 'port' ]
946 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
947
948 main.log.info( "Deactivating reactive forwarding app " )
949 deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
950 if activateResult and deactivateResult and main.hostsData:
951 main.log.info( "Successfully used fwd app to discover hosts " )
952 getDataResult = main.TRUE
953 else:
954 main.log.info( "Failed to use fwd app to discover hosts " )
955 getDataResult = main.FALSE
956
957 print main.hostsData
958
959 return getDataResult
960
961def checkTopology( main, expectedLink ):
962 statusResult = main.TRUE
963 # Check onos topology
964 main.log.info( itemName + ": Checking ONOS topology " )
965
966 for i in range( main.numCtrls ):
967 topologyResult = main.CLIs[ i ].topology()
968 statusResult = main.ONOSbench.checkStatus( topologyResult,
969 main.numSwitch,
970 expectedLink )\
971 and statusResult
972 if not statusResult:
973 main.log.error( itemName + ": Topology mismatch" )
974 else:
975 main.log.info( itemName + ": Topology match" )
976 return statusResult
977
978def checkIntentState( main, intentsId ):
979 """
980 This function will check intent state to make sure all the intents
981 are in INSTALLED state
982 """
983
984 intentResult = main.TRUE
985 results = []
986
987 main.log.info( itemName + ": Checking intents state" )
988 # First check of intents
989 for i in range( main.numCtrls ):
990 tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
991 results.append( tempResult )
992
993 expectedState = [ 'INSTALLED', 'INSTALLING' ]
994
995 if all( result == main.TRUE for result in results ):
996 main.log.info( itemName + ": Intents are installed correctly" )
997 else:
998 # Wait for at least 5 second before checking the intents again
999 time.sleep( 5 )
1000 results = []
1001 # Second check of intents since some of the intents may be in
1002 # INSTALLING state, they should be in INSTALLED at this time
1003 for i in range( main.numCtrls ):
1004 tempResult = main.CLIs[ i ].checkIntentState(
1005 intentsId=intentsId )
1006 results.append( tempResult )
1007 if all( result == main.TRUE for result in results ):
1008 main.log.info( itemName + ": Intents are installed correctly" )
1009 else:
1010 main.log.error( itemName + ": Intents are NOT installed correctly" )
1011 intentResult = main.FALSE
1012
1013 return intentResult
1014
1015def checkFlowsState( main ):
1016
1017 main.log.info( itemName + ": Check flows state" )
1018 checkFlowsResult = main.CLIs[ 0 ].checkFlowsState()
1019 return checkFlowsResult
1020
1021def link( main, sw1, sw2, option):
1022
1023 # link down
1024 main.log.info( itemName + ": Bring link " + option + "between " +
1025 sw1 + " and " + sw2 )
1026 linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
1027 return linkResult
1028
1029def removeAllIntents( main, intentsId ):
1030 """
1031 Remove all intents in the intentsId
1032 """
1033
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001034 onosSummary = []
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001035 removeIntentResult = main.TRUE
1036 # Remove intents
1037 for intent in intentsId:
1038 main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
1039
1040 time.sleep( 5 )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001041
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001042 # If there is remianing intents then remove intents should fail
1043 for i in range( main.numCtrls ):
1044 onosSummary.append( json.loads( main.CLIs[ i ].summary() ) )
1045
1046 for summary in onosSummary:
1047 if summary.get( 'intents' ) != 0:
1048 main.log.warn( itemName + ": There are " +
1049 str( summary.get( 'intents' ) ) +
1050 " intents remaining in node " +
1051 str( summary.get( 'node' ) ) +
1052 ", failed to remove all the intents " )
1053 removeIntentResult = main.FALSE
1054
1055 if removeIntentResult:
1056 main.log.info( itemName + ": There are no more intents remaining, " +
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001057 "successfully removed all the intents." )
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001058
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001059 return removeIntentResult
1060
1061def checkFlowsCount( main ):
1062 """
1063 Check flows count in each node
1064 """
1065
1066 flowsCount = []
1067 main.log.info( itemName + ": Checking flows count in each ONOS node" )
1068 for i in range( main.numCtrls ):
1069 summaryResult = main.CLIs[ i ].summary()
1070 if not summaryResult:
1071 main.log.error( itemName + ": There is something wrong with " +
1072 "summary command" )
1073 return main.FALSE
1074 else:
1075 summaryJson = json.loads( summaryResult )
1076 flowsCount.append( summaryJson.get( 'flows' ) )
1077
1078 if flowsCount:
1079 if all( flows==flowsCount[ 0 ] for flows in flowsCount ):
1080 main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
1081 " flows in all ONOS node" )
1082 else:
1083 for i in range( main.numCtrls ):
1084 main.log.debug( itemName + ": ONOS node " + str( i ) + " has " +
kelvin-onlab6dea6e62015-07-23 13:07:26 -07001085 str( flowsCount[ i ] ) + " flows" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001086 else:
1087 main.log.error( "Checking flows count failed, check summary command" )
1088 return main.FALSE
1089
1090 return main.TRUE
1091
acsmarse6b410f2015-07-17 14:39:34 -07001092def checkLeaderChange( leaders1 , leaders2 ):
1093 """
1094 Checks for a change in intent partition leadership.
1095
1096 Takes the output of leaders -c in json string format before and after
1097 a potential change as input
1098
1099 Returns main.TRUE if no mismatches are detected
1100 Returns main.FALSE if there is a mismatch or on error loading the input
1101 """
1102 try:
1103 leaders1 = json.loads( leaders1 )
1104 leaders2 = json.loads( leaders2 )
1105 except ( AttributeError, TypeError):
1106 main.log.exception( self.name + ": Object not as expected" )
1107 return main.FALSE
1108 except Exception:
1109 main.log.exception( self.name + ": Uncaught exception!" )
1110 main.cleanup()
1111 main.exit()
1112 main.log.info( "Checking Intent Paritions for Change in Leadership" )
1113 mismatch = False
1114 for dict1 in leaders1:
1115 if "intent" in dict1.get( "topic", [] ):
1116 for dict2 in leaders2:
1117 if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
1118 dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
1119 mismatch = True
1120 main.log.error( "{0} changed leader from {1} to {2}".\
1121 format( dict1.get( "topic", "no-topic" ),\
1122 dict1.get( "leader", "no-leader" ),\
1123 dict2.get( "leader", "no-leader" ) ) )
1124 if mismatch:
1125 return main.FALSE
1126 else:
1127 return main.TRUE