1
2
3 import time
4 import pexpect
5 import sys
6 import json
7 from drivers.common.clidriver import CLI
8
9
11
14
15
16 - def connect( self, **connectargs ):
17 for key in connectargs:
18 vars( self )[ key ] = connectargs[ key ]
19 self.name = self.options[ 'name' ]
20 self.handle = super( QuaggaCliDriver, self ).connect(
21 user_name=self.user_name,
22 ip_address="127.0.0.1",
23 port=self.port,
24 pwd=self.pwd )
25 if self.handle:
26 return self.handle
27 else:
28 main.log.info( "NO HANDLE" )
29 return main.FALSE
30
32 self.name = self.options[ 'name' ]
33
34
35
36 self.handle = super( QuaggaCliDriver, self ).connect(
37 user_name=self.user_name,
38 ip_address="1.1.1.1",
39 port=self.port,
40 pwd=self.pwd )
41
42
43
44
45 if self.handle:
46
47
48 self.handle.sendline( "telnet localhost 2605" )
49
50 self.handle.expect( "Password:" )
51 self.handle.sendline( "hello" )
52
53 self.handle.expect( "bgpd" )
54 self.handle.sendline( "enable" )
55
56 self.handle.expect( "bgpd#" )
57 return self.handle
58 else:
59 main.log.info( "NO HANDLE" )
60 return main.FALSE
61
63 self.name = self.options[ 'name' ]
64 self.handle = super( QuaggaCliDriver, self ).connect(
65 user_name=self.user_name, ip_address=ip_address,
66 port=self.port, pwd=self.pwd )
67 main.log.info( "connect parameters:" + str( self.user_name ) + ";"
68 + str( self.ip_address ) + ";" + str( self.port )
69 + ";" + str( self.pwd ) )
70
71 if self.handle:
72
73
74 self.handle.sendline( "telnet localhost 2605" )
75
76 self.handle.expect( "Password:" )
77 self.handle.sendline( "hello" )
78
79 self.handle.expect( "bgpd" )
80 self.handle.sendline( "enable" )
81
82 self.handle.expect( "bgpd#" )
83 main.log.info( "I am in quagga on host " + str( ip_address ) )
84
85 return self.handle
86 else:
87 main.log.info( "NO HANDLE" )
88 return main.FALSE
89
91 main.log.info( "I am in enter_config method!" )
92 try:
93 self.handle.sendline( "" )
94 self.handle.expect( "bgpd#" )
95 except Exception:
96 main.log.warn( "Probably not currently in enable mode!" )
97 self.disconnect()
98 return main.FALSE
99 self.handle.sendline( "configure terminal" )
100 self.handle.expect( "config", timeout=5 )
101 routerAS = "router bgp " + str( asn )
102 try:
103 self.handle.sendline( routerAS )
104 self.handle.expect( "config-router", timeout=5 )
105 return main.TRUE
106 except Exception:
107 return main.FALSE
108
110 main.log.info( "I am in generate_prefixes method!" )
111
112
113
114 routes = []
115 routesGen = 0
116 m = numRoutes / 256
117 n = numRoutes % 256
118
119 for i in range( 0, m ):
120 for j in range( 0, 256 ):
121 network = str( net ) + "." + str( i ) + "." + str( j ) \
122 + ".0/24"
123 routes.append( network )
124 routesGen = routesGen + 1
125
126 for j in range( 0, n ):
127 network = str( net ) + "." + str( m ) + "." + str( j ) + ".0/24"
128 routes.append( network )
129 routesGen = routesGen + 1
130
131 if routesGen == numRoutes:
132 main.log.info( "Successfully generated " + str( numRoutes )
133 + " prefixes!" )
134 return routes
135 return main.FALSE
136
137
138
141
142 ingresses = []
143 egress = ""
144 for peer in sdnipData[ 'bgpPeers' ]:
145 if peer[ 'ipAddress' ] == nextHop:
146 egress = "of:" + str(
147 peer[ 'attachmentDpid' ] ).replace( ":", "" ) + ":" \
148 + str( peer[ 'attachmentPort' ] )
149 for peer in sdnipData[ 'bgpPeers' ]:
150 if not peer[ 'ipAddress' ] == nextHop:
151 ingress = "of:" + str(
152 peer[ 'attachmentDpid' ] ).replace( ":", "" ) + ":" \
153 + str( peer[ 'attachmentPort' ] )
154 if not ingress == egress and ingress not in ingresses:
155 ingresses.append( ingress )
156
157
158
159
160 selector = "ETH_TYPE{ethType=800},IPV4_DST{ip=" + prefix + "}"
161 treatment = "[ETH_DST{mac=" + str( nextHopMac ) + "}]"
162
163 intent = egress + "/" + str( sorted( ingresses ) ) + "/" + \
164 selector + "/" + treatment
165 return intent
166
169 intents = []
170 sdnipJsonFile = open( sdnipJsonFilePath ).read()
171
172 sdnipData = json.loads( sdnipJsonFile )
173
174 for prefix in prefixes:
175 intents.append(
176 self.generateExpectedSingleRouteIntent(
177 prefix, nextHop, nextHopMac, sdnipData ) )
178 return sorted( intents )
179
180
181
185
186
188 routesJsonObj = json.loads( getRoutesResult )
189
190 allRoutesActual = []
191 for route in routesJsonObj['routes4']:
192 if 'prefix' in route:
193 if route[ 'prefix' ] == '172.16.10.0/24':
194 continue
195 allRoutesActual.append(
196 route[ 'prefix' ] + "/" + route[ 'nextHop' ] )
197
198 return sorted( allRoutesActual )
199
201 routesJsonObj = json.loads( getRoutesResult )
202
203 allRoutesActual = []
204 for route in routesJsonObj['routes4']:
205 if route[ 'prefix' ] == '172.16.10.0/24':
206 continue
207 allRoutesActual.append(
208 route[ 'prefix' ] + "/" + route[ 'nextHop' ] )
209
210 return sorted( allRoutesActual )
211
212
214 intents = []
215
216
217 intentsJsonObj = json.loads( getIntentsResult )
218
219 for intent in intentsJsonObj:
220
221
222 if intent[ 'type' ] == "MultiPointToSinglePointIntent" \
223 and intent[ 'state' ] == 'INSTALLED':
224 egress = str( intent[ 'egress' ][ 'device' ] ) + ":" \
225 + str( intent[ 'egress' ][ 'port' ] )
226 ingress = []
227 for attachmentPoint in intent[ 'ingress' ]:
228 ingress.append(
229 str( attachmentPoint[ 'device' ] ) + ":"
230 + str( attachmentPoint[ 'port' ] ) )
231
232 selector = intent[ 'selector' ].replace(
233 "[", "" ).replace( "]", "" ).replace( " ", "" )
234 if str( selector ).startswith( "IPV4" ):
235 str1, str2 = str( selector ).split( "," )
236 selector = str2 + "," + str1
237
238 intent = egress + "/" + str( sorted( ingress ) ) + "/" + \
239 selector + "/" + intent[ 'treatment' ]
240 intents.append( intent )
241 return sorted( intents )
242
243
245 intentsJsonObj = json.loads( getIntentsResult )
246 num = 0
247 for intent in intentsJsonObj:
248 if intent[ 'type' ] == "MultiPointToSinglePointIntent" \
249 and intent[ 'state' ] == 'INSTALLED':
250 num = num + 1
251 return num
252
253
255 intentsJsonObj = json.loads( getIntentsResult )
256 num = 0
257 for intent in intentsJsonObj:
258 if intent[ 'type' ] == "PointToPointIntent" \
259 and intent[ 'state' ] == 'INSTALLED':
260 num = num + 1
261 return num
262
263
265 intents = []
266
267
268 intentsJsonObj = json.loads( getIntentsResult )
269
270 for intent in intentsJsonObj:
271
272
273 if intent[ 'type' ] == "PointToPointIntent" \
274 and "protocol=6" in str( intent[ 'selector' ] ):
275 ingress = str( intent[ 'ingress' ][ 'device' ] ) + ":" \
276 + str( intent[ 'ingress' ][ 'port' ] )
277 egress = str( intent[ 'egress' ][ 'device' ] ) + ":" + \
278 str( intent[ 'egress' ][ 'port' ] )
279 selector = str( intent[ 'selector' ] ).replace( " ", "" )\
280 .replace( "[", "" ).replace( "]", "" ).split( "," )
281 intent = ingress + "/" + egress + "/" + \
282 str( sorted( selector ) )
283 intents.append( intent )
284
285 return sorted( intents )
286
287
288
290 from operator import eq
291
292 sdnipJsonFile = open( sdnipJsonFilePath ).read()
293 sdnipData = json.loads( sdnipJsonFile )
294
295 intents = []
296 bgpPeerAttachmentPoint = ""
297 bgpSpeakerAttachmentPoint = "of:" + str(
298 sdnipData[ 'bgpSpeakers' ][ 0 ][ 'attachmentDpid' ] )\
299 .replace( ":", "" ) + ":" \
300 + str( sdnipData[ 'bgpSpeakers' ][ 0 ][ 'attachmentPort' ] )
301 for peer in sdnipData[ 'bgpPeers' ]:
302 bgpPeerAttachmentPoint = "of:" \
303 + str( peer[ 'attachmentDpid' ] ).replace( ":", "" ) \
304 + ":" + str( peer[ 'attachmentPort' ] )
305
306 bgpSpeakerIpAddress = ""
307 for interfaceAddress in \
308 sdnipData[ 'bgpSpeakers' ][ 0 ][ 'interfaceAddresses' ]:
309
310
311
312
313 if eq( interfaceAddress[ 'interfaceDpid' ],
314 peer[ 'attachmentDpid' ] ) \
315 and eq( interfaceAddress[ 'interfacePort' ],
316 peer[ 'attachmentPort' ] ):
317 bgpSpeakerIpAddress = interfaceAddress[ 'ipAddress' ]
318 break
319 else:
320 continue
321
322
323
324 selectorStr = "IPV4_SRC{ip=" + bgpSpeakerIpAddress + "/32}," \
325 + "IPV4_DST{ip=" + peer[ 'ipAddress' ] + "/32}," \
326 + "IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, \
327 TCP_DST{tcpPort=179}"
328 selector = selectorStr.replace( " ", "" ).replace("[", "" )\
329 .replace( "]", "" ).split( "," )
330 intent = bgpSpeakerAttachmentPoint + "/" + \
331 bgpPeerAttachmentPoint + "/" + str( sorted( selector ) )
332 intents.append( intent )
333
334 selectorStr = "IPV4_SRC{ip=" + bgpSpeakerIpAddress + "/32}," \
335 + "IPV4_DST{ip=" + peer[ 'ipAddress' ] + "/32}," \
336 + "IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, \
337 TCP_SRC{tcpPort=179}"
338 selector = selectorStr.replace( " ", "" ).replace("[", "" )\
339 .replace( "]", "" ).split( "," )
340 intent = bgpSpeakerAttachmentPoint + "/" \
341 + bgpPeerAttachmentPoint + "/" + str( sorted( selector ) )
342 intents.append( intent )
343
344
345
346 selectorStr = "IPV4_SRC{ip=" + peer[ 'ipAddress' ] + "/32}," \
347 + "IPV4_DST{ip=" + bgpSpeakerIpAddress + "/32}," \
348 + "IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, \
349 TCP_DST{tcpPort=179}"
350 selector = selectorStr.replace( " ", "" ).replace("[", "" )\
351 .replace( "]", "" ).split( "," )
352 intent = bgpPeerAttachmentPoint + "/" \
353 + bgpSpeakerAttachmentPoint + "/" + str( sorted( selector ) )
354 intents.append( intent )
355
356 selectorStr = "IPV4_SRC{ip=" + peer[ 'ipAddress' ] + "/32}," \
357 + "IPV4_DST{ip=" + bgpSpeakerIpAddress + "/32}," \
358 + "IP_PROTO{protocol=6}, ETH_TYPE{ethType=800}, \
359 TCP_SRC{tcpPort=179}"
360 selector = selectorStr.replace( " ", "" ).replace( "[", "" )\
361 .replace( "]", "" ).split( "," )
362 intent = bgpPeerAttachmentPoint + "/" \
363 + bgpSpeakerAttachmentPoint + "/" + str( sorted( selector ) )
364 intents.append( intent )
365
366 return sorted( intents )
367
369 main.log.info( "I am in add_routes method!" )
370
371 routesAdded = 0
372 try:
373 self.handle.sendline( "" )
374
375 self.handle.expect( "config-router", timeout=5 )
376 except Exception:
377 main.log.warn( "Probably not in config-router mode!" )
378 self.disconnect()
379 main.log.info( "Start to add routes" )
380
381 chunk_size = 20
382
383 if len(routes) > chunk_size:
384 num_iter = (int) (len(routes) / chunk_size)
385 else:
386 num_iter = 1;
387
388 total = 0
389 for n in range( 0, num_iter + 1):
390 routeCmd = ""
391 if (len( routes ) - (n * chunk_size)) >= chunk_size:
392 m = (n + 1) * chunk_size
393 else:
394 m = len( routes )
395 for i in range( n * chunk_size, m ):
396 routeCmd = routeCmd + "network " + routes[ i ] + "\n"
397 total = total + 1
398
399 main.log.info(routeCmd)
400 try:
401 self.handle.sendline( routeCmd )
402 self.handle.expect( "bgpd", timeout=5 )
403 except Exception:
404 main.log.warn( "Failed to add route" )
405 self.disconnect()
406
407
408 main.log.info("Total routes so far " + ((str) (total)) + " wait for 0 sec")
409
410 if routesAdded == len( routes ):
411 main.log.info( "Finished adding routes" )
412 return main.TRUE
413 return main.FALSE
414
416 main.log.info( "I am in delete_routes method!" )
417
418 routesAdded = 0
419 try:
420 self.handle.sendline( "" )
421
422 self.handle.expect( "config-router", timeout=5 )
423 except Exception:
424 main.log.warn( "Probably not in config-router mode!" )
425 self.disconnect()
426 main.log.info( "Start to delete routes" )
427
428 for i in range( 0, len( routes ) ):
429 routeCmd = "no network " + routes[ i ]
430 try:
431 self.handle.sendline( routeCmd )
432 self.handle.expect( "bgpd", timeout=5 )
433 except Exception:
434 main.log.warn( "Failed to delete route" )
435 self.disconnect()
436
437
438 if routesAdded == len( routes ):
439 main.log.info( "Finished deleting routes" )
440 return main.TRUE
441 return main.FALSE
442
443 - def pingTest( self, ip_address, pingTestFile, pingTestResultFile ):
444 main.log.info( "Start the ping test on host:" + str( ip_address ) )
445
446 self.name = self.options[ 'name' ]
447 self.handle = super( QuaggaCliDriver, self ).connect(
448 user_name=self.user_name, ip_address=ip_address,
449 port=self.port, pwd=self.pwd )
450 main.log.info( "connect parameters:" + str( self.user_name ) + ";"
451 + str( self.ip_address ) + ";" + str( self.port )
452 + ";" + str( self.pwd ) )
453
454 if self.handle:
455
456
457 main.log.info( "I in host " + str( ip_address ) )
458 main.log.info( pingTestFile + " > " + pingTestResultFile + " &" )
459 self.handle.sendline(
460 pingTestFile +
461 " > " +
462 pingTestResultFile +
463 " &" )
464 self.handle.expect( "\$", timeout=60 )
465 handle = self.handle.before
466
467 return handle
468 else:
469 main.log.info( "NO HANDLE" )
470 return main.FALSE
471
472
473
474 - def addRoute( self, net, numRoutes, routeRate ):
475 try:
476 self.handle.sendline( "" )
477 self.handle.expect( "config-router" )
478 except Exception:
479 main.log.warn( "Probably not in config-router mode!" )
480 self.disconnect()
481 main.log.info( "Adding Routes" )
482 j = 0
483 k = 0
484 while numRoutes > 255:
485 numRoutes = numRoutes - 255
486 j = j + 1
487 k = numRoutes % 254
488 routesAdded = 0
489 if numRoutes > 255:
490 numRoutes = 255
491 for m in range( 1, j + 1 ):
492 for n in range( 1, numRoutes + 1 ):
493 network = str( net ) + "." + str( m ) + "." + str( n ) \
494 + ".0/24"
495 routeCmd = "network " + network
496 try:
497 self.handle.sendline( routeCmd )
498 self.handle.expect( "bgpd" )
499 except Exception:
500 main.log.warn( "failed to add route" )
501 self.disconnect()
502 waitTimer = 1.00 / routeRate
503 time.sleep( waitTimer )
504 routesAdded = routesAdded + 1
505 for d in range( j + 1, j + 2 ):
506 for e in range( 1, k + 1 ):
507 network = str( net ) + "." + str( d ) + "." + str( e ) \
508 + ".0/24"
509 routeCmd = "network " + network
510 try:
511 self.handle.sendline( routeCmd )
512 self.handle.expect( "bgpd" )
513 except Exception:
514 main.log.warn( "failed to add route" )
515 self.disconnect()
516 waitTimer = 1.00 / routeRate
517 time.sleep( waitTimer )
518 routesAdded = routesAdded + 1
519 if routesAdded == numRoutes:
520 return main.TRUE
521 return main.FALSE
522
523
524 - def delRoute( self, net, numRoutes, routeRate ):
525 try:
526 self.handle.sendline( "" )
527 self.handle.expect( "config-router" )
528 except Exception:
529 main.log.warn( "Probably not in config-router mode!" )
530 self.disconnect()
531 main.log.info( "Deleting Routes" )
532 j = 0
533 k = 0
534 while numRoutes > 255:
535 numRoutes = numRoutes - 255
536 j = j + 1
537 k = numRoutes % 254
538 routesDeleted = 0
539 if numRoutes > 255:
540 numRoutes = 255
541 for m in range( 1, j + 1 ):
542 for n in range( 1, numRoutes + 1 ):
543 network = str( net ) + "." + str( m ) + "." + str( n ) \
544 + ".0/24"
545 routeCmd = "no network " + network
546 try:
547 self.handle.sendline( routeCmd )
548 self.handle.expect( "bgpd" )
549 except Exception:
550 main.log.warn( "Failed to delete route" )
551 self.disconnect()
552 waitTimer = 1.00 / routeRate
553 time.sleep( waitTimer )
554 routesDeleted = routesDeleted + 1
555 for d in range( j + 1, j + 2 ):
556 for e in range( 1, k + 1 ):
557 network = str( net ) + "." + str( d ) + "." + str( e ) \
558 + ".0/24"
559 routeCmd = "no network " + network
560 try:
561 self.handle.sendline( routeCmd )
562 self.handle.expect( "bgpd" )
563 except Exception:
564 main.log.warn( "Failed to delete route" )
565 self.disconnect()
566 waitTimer = 1.00 / routeRate
567 time.sleep( waitTimer )
568 routesDeleted = routesDeleted + 1
569 if routesDeleted == numRoutes:
570 return main.TRUE
571 return main.FALSE
572
574 def pronto( ip, user, passwd ):
575 print "Connecting to Pronto switch"
576 child = pexpect.spawn( "telnet " + ip )
577 i = child.expect( [ "login:", "CLI#", pexpect.TIMEOUT ] )
578 if i == 0:
579 print "user_name and password required. Passing login info."
580 child.sendline( user )
581 child.expect( "Password:" )
582 child.sendline( passwd )
583 child.expect( "CLI#" )
584 print "Logged in, getting flowtable."
585 child.sendline( "flowtable brief" )
586 for t in range( 9 ):
587 t2 = 9 - t
588 print "\r" + str( t2 )
589 sys.stdout.write( "\033[F" )
590 time.sleep( 1 )
591 print "Scanning flowtable"
592 child.expect( "Flow table show" )
593 count = 0
594 while True:
595 i = child.expect( [ '17\d\.\d{1,3}\.\d{1,3}\.\d{1,3}',
596 'CLI#', pexpect.TIMEOUT ] )
597 if i == 0:
598 count = count + 1
599 elif i == 1:
600 print "Pronto flows: " + str( count ) + "\nDone\n"
601 break
602 else:
603 break
604
605 def cisco( ip, user, passwd ):
606 print "Establishing Cisco switch connection"
607 child = pexpect.spawn( "ssh " + user + "@" + ip )
608 i = child.expect( [ "Password:", "CLI#", pexpect.TIMEOUT ] )
609 if i == 0:
610 print "Password required. Passing now."
611 child.sendline( passwd )
612 child.expect( "#" )
613 print "Logged in. Retrieving flow table then counting flows."
614 child.sendline( "show openflow switch all flows all" )
615 child.expect( "Logical Openflow Switch" )
616 print "Flow table retrieved. Counting flows"
617 count = 0
618 while True:
619 i = child.expect( [ "nw_src=17", "#", pexpect.TIMEOUT ] )
620 if i == 0:
621 count = count + 1
622 elif i == 1:
623 print "Cisco flows: " + str( count ) + "\nDone\n"
624 break
625 else:
626 break
627 if brand == "pronto" or brand == "PRONTO":
628 pronto( ip, user, passwd )
629
630
631
633 main.log.info( "I am in disconnect_peer_session method!" )
634
635 try:
636 self.handle.sendline( "" )
637
638 self.handle.expect( "config-router", timeout=5 )
639 except Exception:
640 main.log.warn( "Probably not in config-router mode!" )
641 self.disconnect()
642 main.log.info( "Start to disable peer" )
643
644 cmd = "no neighbor " + peer + " remote-as " + peer_as
645 try:
646 self.handle.sendline( cmd )
647 self.handle.expect( "bgpd", timeout=5 )
648 except Exception:
649 main.log.warn( "Failed to disable peer" )
650 self.disconnect()
651
653 main.log.info( "I am in enable_bgp_peer method!" )
654
655 try:
656 self.handle.sendline( "" )
657
658 self.handle.expect( "config-router", timeout=5 )
659 except Exception:
660 main.log.warn( "Probably not in config-router mode!" )
661 self.disconnect()
662 main.log.info( "Start to disable peer" )
663
664 cmd = "neighbor " + peer + " remote-as " + peer_as
665 try:
666 self.handle.sendline( cmd )
667 self.handle.expect( "bgpd", timeout=5 )
668 except Exception:
669 main.log.warn( "Failed to enable peer" )
670 self.disconnect()
671
673 """
674 Called when Test is complete to disconnect the Quagga handle.
675 """
676 response = ''
677 try:
678 self.handle.close()
679 except Exception:
680 main.log.error( "Connection failed to the host" )
681 response = main.FALSE
682 return response
683