blob: 2661a0754645c648f540036192b9f46a8a57d973 [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
2This file contains classes for CHOTestMonkey that are related to application event
3Author: you@onlab.us
4"""
5from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
6from tests.CHOTestMonkey.dependencies.elements.ONOSElement import HostIntent, PointIntent
7
Jon Hall2bb3e212017-05-24 17:07:25 -07008
You Wangdb927a52016-02-26 11:03:28 -08009class IntentEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -070010
You Wangdb927a52016-02-26 11:03:28 -080011 def __init__( self ):
12 Event.__init__( self )
13 # The index of the ONOS CLI that is going to run the command
14 self.CLIIndex = 0
15
You Wang7a27f3a2016-07-05 10:12:27 -070016 def getRandomCorrespondent( self, hostA, connected=True ):
17 import random
18 if connected:
19 candidates = hostA.correspondents
20 else:
21 candidates = [ host for host in main.hosts if host not in hostA.correspondents and host != hostA ]
22 if len( candidates ) == 0:
23 return None
Jon Hall2bb3e212017-05-24 17:07:25 -070024 hostB = random.sample( candidates, 1 )[ 0 ]
You Wang7a27f3a2016-07-05 10:12:27 -070025 return hostB
26
27 def getRandomHostPair( self, connected=True ):
28 import random
29 candidateDict = {}
30 with main.variableLock:
31 for host in main.hosts:
32 correspondent = self.getRandomCorrespondent( host, connected=connected )
Jon Hall2bb3e212017-05-24 17:07:25 -070033 if correspondent is not None:
You Wang7a27f3a2016-07-05 10:12:27 -070034 candidateDict[ host ] = correspondent
35 if candidateDict == {}:
36 return None
Jon Hall2bb3e212017-05-24 17:07:25 -070037 hostA = random.sample( candidateDict.keys(), 1 )[ 0 ]
You Wang7a27f3a2016-07-05 10:12:27 -070038 hostB = candidateDict[ hostA ]
39 return [ hostA, hostB ]
40
41 def getIntentsByType( self, intentType ):
42 intents = []
43 with main.variableLock:
44 for intent in main.intents:
45 if intent.type == intentType:
46 intents.append( intent )
47 return intents
48
49 def getRandomIntentByType( self, intentType ):
50 import random
51 intents = self.getIntentsByType( intentType )
52 if len( intents ) == 0:
53 return None
54 intent = random.sample( intents, 1 )[ 0 ]
55 return intent
56
Jon Hall2bb3e212017-05-24 17:07:25 -070057
You Wangdb927a52016-02-26 11:03:28 -080058class HostIntentEvent( IntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070059
You Wangdb927a52016-02-26 11:03:28 -080060 def __init__( self ):
61 IntentEvent.__init__( self )
62 self.hostA = None
63 self.hostB = None
64
65 def startHostIntentEvent( self ):
66 return EventStates().PASS
67
68 def startEvent( self, args ):
69 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070070 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080071 if self.typeIndex == EventType().APP_INTENT_HOST_ADD or self.typeIndex == EventType().APP_INTENT_HOST_DEL:
72 if len( args ) < 3:
73 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
74 return EventStates().ABORT
75 elif len( args ) > 3:
76 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
77 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -070078 try:
79 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
80 if self.typeIndex == EventType().APP_INTENT_HOST_ADD:
81 hostPairRandom = self.getRandomHostPair( connected=False )
Jon Hall2bb3e212017-05-24 17:07:25 -070082 if hostPairRandom is None:
You Wang59dfeb62016-07-14 09:47:33 -070083 main.log.warn( "All host pairs are connected, aborting event" )
84 return EventStates().ABORT
85 self.hostA = hostPairRandom[ 0 ]
86 self.hostB = hostPairRandom[ 1 ]
87 elif self.typeIndex == EventType().APP_INTENT_HOST_DEL:
88 intent = self.getRandomIntentByType( 'INTENT_HOST' )
Jon Hall2bb3e212017-05-24 17:07:25 -070089 if intent is None:
You Wang59dfeb62016-07-14 09:47:33 -070090 main.log.warn( "No host intent for deletion, aborting event" )
91 return EventStates().ABORT
92 self.hostA = intent.hostA
93 self.hostB = intent.hostB
94 elif args[ 0 ] == args[ 1 ]:
95 main.log.warn( "%s - invalid argument: %s, %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
You Wangdb927a52016-02-26 11:03:28 -080096 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -070097 else:
98 for host in main.hosts:
99 if host.name == args[ 0 ]:
100 self.hostA = host
101 elif host.name == args[ 1 ]:
102 self.hostB = host
Jon Hall2bb3e212017-05-24 17:07:25 -0700103 if self.hostA is not None and self.hostB is not None:
You Wang59dfeb62016-07-14 09:47:33 -0700104 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700105 if self.hostA is None:
You Wang59dfeb62016-07-14 09:47:33 -0700106 main.log.warn( "Host %s does not exist: " % ( args[ 0 ] ) )
107 return EventStates().ABORT
Jon Hall2bb3e212017-05-24 17:07:25 -0700108 if self.hostB is None:
You Wang59dfeb62016-07-14 09:47:33 -0700109 main.log.warn( "Host %s does not exist: " % ( args[ 1 ] ) )
110 return EventStates().ABORT
111 index = int( args[ 2 ] )
112 if index < 1 or index > int( main.numCtrls ):
113 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
You Wangdb927a52016-02-26 11:03:28 -0800114 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -0700115 if not main.controllers[ index - 1 ].isUp():
116 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
117 return EventStates().ABORT
118 self.CLIIndex = index
119 return self.startHostIntentEvent()
120 except Exception:
121 main.log.warn( "Caught exception, aborting event" )
You Wang7a27f3a2016-07-05 10:12:27 -0700122 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800123
Jon Hall2bb3e212017-05-24 17:07:25 -0700124
You Wangdb927a52016-02-26 11:03:28 -0800125class AddHostIntent( HostIntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700126
You Wangdb927a52016-02-26 11:03:28 -0800127 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700128 Add a host-to-host intent ( bidirectional )
You Wangdb927a52016-02-26 11:03:28 -0800129 """
130 def __init__( self ):
131 HostIntentEvent.__init__( self )
132 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700133 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800134
135 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700136 try:
Jon Hall2bb3e212017-05-24 17:07:25 -0700137 assert self.hostA is not None and self.hostB is not None
You Wang7a27f3a2016-07-05 10:12:27 -0700138 # Check whether there already exists some intent for the host pair
139 # For now we should avoid installing overlapping intents
140 for intent in main.intents:
141 if not intent.type == 'INTENT_HOST':
142 continue
143 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
Jon Hall2bb3e212017-05-24 17:07:25 -0700144 intent.hostB == self.hostA and intent.hostA == self.hostB:
You Wang7a27f3a2016-07-05 10:12:27 -0700145 main.log.warn( self.typeString + " - find an exiting intent for the host pair, abort installation" )
146 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700147 main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.hostA.name, self.hostB.name, self.CLIIndex ) )
You Wang7a27f3a2016-07-05 10:12:27 -0700148 controller = main.controllers[ self.CLIIndex - 1 ]
149 with controller.CLILock:
150 id = controller.CLI.addHostIntent( self.hostA.id, self.hostB.id )
Jon Hall2bb3e212017-05-24 17:07:25 -0700151 if id is None:
You Wang7a27f3a2016-07-05 10:12:27 -0700152 main.log.warn( self.typeString + " - add host intent failed" )
153 return EventStates().FAIL
154 with main.variableLock:
155 newHostIntent = HostIntent( id, self.hostA, self.hostB )
156 if self.hostA.isDown() or self.hostA.isRemoved() or self.hostB.isDown() or self.hostB.isRemoved():
157 newHostIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700158 else:
159 newHostIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700160 main.intents.append( newHostIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700161 return EventStates().PASS
162 except Exception:
163 main.log.warn( "Caught exception, aborting event" )
164 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800165
Jon Hall2bb3e212017-05-24 17:07:25 -0700166
You Wangdb927a52016-02-26 11:03:28 -0800167class DelHostIntent( HostIntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700168
You Wangdb927a52016-02-26 11:03:28 -0800169 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700170 Delete a host-to-host intent ( bidirectional )
You Wangdb927a52016-02-26 11:03:28 -0800171 """
172 def __init__( self ):
173 HostIntentEvent.__init__( self )
174 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700175 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800176
177 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700178 try:
Jon Hall2bb3e212017-05-24 17:07:25 -0700179 assert self.hostA is not None and self.hostB is not None
You Wang7a27f3a2016-07-05 10:12:27 -0700180 targetIntent = None
181 for intent in main.intents:
182 if not intent.type == 'INTENT_HOST':
183 continue
184 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
Jon Hall2bb3e212017-05-24 17:07:25 -0700185 intent.hostB == self.hostA and intent.hostA == self.hostB:
You Wang7a27f3a2016-07-05 10:12:27 -0700186 targetIntent = intent
187 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700188 if targetIntent is None:
You Wang7a27f3a2016-07-05 10:12:27 -0700189 main.log.warn( self.typeString + " - intent does not exist" )
190 return EventStates().FAIL
You Wang52163202016-07-14 16:37:15 -0700191 main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.hostA.name, self.hostB.name, self.CLIIndex ) )
You Wang7a27f3a2016-07-05 10:12:27 -0700192 controller = main.controllers[ self.CLIIndex - 1 ]
193 with controller.CLILock:
194 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
Jon Hall2bb3e212017-05-24 17:07:25 -0700195 if result is None or result == main.FALSE:
You Wang7a27f3a2016-07-05 10:12:27 -0700196 main.log.warn( self.typeString + " - delete host intent failed" )
197 return EventStates().FAIL
198 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700199 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700200 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700201 return EventStates().PASS
202 except Exception:
203 main.log.warn( "Caught exception, aborting event" )
204 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800205
Jon Hall2bb3e212017-05-24 17:07:25 -0700206
You Wangdb927a52016-02-26 11:03:28 -0800207class PointIntentEvent( IntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700208
You Wangdb927a52016-02-26 11:03:28 -0800209 def __init__( self ):
210 IntentEvent.__init__( self )
211 self.deviceA = None
212 self.deviceB = None
213
214 def startPointIntentEvent( self ):
215 return EventStates().PASS
216
217 def startEvent( self, args ):
218 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -0700219 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -0800220 if self.typeIndex == EventType().APP_INTENT_POINT_ADD or self.typeIndex == EventType().APP_INTENT_POINT_DEL:
221 if len( args ) < 3:
222 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
223 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700224 elif len( args ) > 4:
You Wangdb927a52016-02-26 11:03:28 -0800225 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
226 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -0700227 try:
228 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
229 if self.typeIndex == EventType().APP_INTENT_POINT_ADD:
230 hostPairRandom = self.getRandomHostPair( connected=False )
Jon Hall2bb3e212017-05-24 17:07:25 -0700231 if hostPairRandom is None:
You Wang59dfeb62016-07-14 09:47:33 -0700232 main.log.warn( "All host pairs are connected, aborting event" )
233 return EventStates().ABORT
234 self.deviceA = hostPairRandom[ 0 ].device
235 self.deviceB = hostPairRandom[ 1 ].device
236 elif self.typeIndex == EventType().APP_INTENT_POINT_DEL:
237 intent = self.getRandomIntentByType( 'INTENT_POINT' )
Jon Hall2bb3e212017-05-24 17:07:25 -0700238 if intent is None:
You Wang59dfeb62016-07-14 09:47:33 -0700239 main.log.warn( "No point intent for deletion, aborting event" )
240 return EventStates().ABORT
241 self.deviceA = intent.deviceA
242 self.deviceB = intent.deviceB
243 elif args[ 0 ] == args[ 1 ]:
244 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
You Wangdb927a52016-02-26 11:03:28 -0800245 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700246 else:
You Wang59dfeb62016-07-14 09:47:33 -0700247 for device in main.devices:
248 if device.name == args[ 0 ]:
249 self.deviceA = device
250 elif device.name == args[ 1 ]:
251 self.deviceB = device
Jon Hall2bb3e212017-05-24 17:07:25 -0700252 if self.deviceA is not None and self.deviceB is not None:
You Wang59dfeb62016-07-14 09:47:33 -0700253 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700254 if self.deviceA is None:
You Wang59dfeb62016-07-14 09:47:33 -0700255 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
256 return EventStates().ABORT
Jon Hall2bb3e212017-05-24 17:07:25 -0700257 if self.deviceB is None:
You Wang59dfeb62016-07-14 09:47:33 -0700258 main.log.warn( "Device %s does not exist: " % ( args[ 1 ] ) )
259 return EventStates().ABORT
260 index = int( args[ 2 ] )
261 if index < 1 or index > int( main.numCtrls ):
262 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
263 return EventStates().ABORT
264 if not main.controllers[ index - 1 ].isUp():
265 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
266 return EventStates().ABORT
267 self.CLIIndex = index
268 if len( args ) == 4 and args[ 3 ] == 'bidirectional':
269 # Install point intents for both directions
270 resultA = self.startPointIntentEvent()
271 [ self.deviceA, self.deviceB ] = [ self.deviceB, self.deviceA ]
272 resultB = self.startPointIntentEvent()
273 if resultA == EventStates().PASS and resultB == EventStates().PASS:
274 return EventStates().PASS
275 else:
276 return EventStates().FAIL
277 else:
278 return self.startPointIntentEvent()
279 except Exception:
280 main.log.warn( "Caught exception, aborting event" )
281 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800282
Jon Hall2bb3e212017-05-24 17:07:25 -0700283
You Wangdb927a52016-02-26 11:03:28 -0800284class AddPointIntent( PointIntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700285
You Wangdb927a52016-02-26 11:03:28 -0800286 """
287 Add a point-to-point intent
288 """
289 def __init__( self ):
290 PointIntentEvent.__init__( self )
291 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700292 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800293
294 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700295 try:
Jon Hall2bb3e212017-05-24 17:07:25 -0700296 assert self.deviceA is not None and self.deviceB is not None
You Wang7a27f3a2016-07-05 10:12:27 -0700297 controller = main.controllers[ self.CLIIndex - 1 ]
You Wang59dfeb62016-07-14 09:47:33 -0700298 # TODO: support multiple hosts under one device
You Wang7a27f3a2016-07-05 10:12:27 -0700299 # Check whether there already exists some intent for the device pair
300 # For now we should avoid installing overlapping intents
301 for intent in main.intents:
302 if not intent.type == 'INTENT_POINT':
303 continue
304 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
305 main.log.warn( self.typeString + " - find an exiting intent for the device pair, abort installation" )
306 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700307 main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.deviceA.name, self.deviceB.name, self.CLIIndex ) )
You Wang7a27f3a2016-07-05 10:12:27 -0700308 controller = main.controllers[ self.CLIIndex - 1 ]
309 with controller.CLILock:
You Wang7a27f3a2016-07-05 10:12:27 -0700310 srcMAC = ""
311 dstMAC = ""
312 if len( self.deviceA.hosts ) > 0:
313 srcMAC = self.deviceA.hosts[ 0 ].mac
314 if len( self.deviceB.hosts ) > 0:
315 dstMAC = self.deviceB.hosts[ 0 ].mac
You Wang59dfeb62016-07-14 09:47:33 -0700316 id = controller.CLI.addPointIntent( self.deviceA.dpid, self.deviceB.dpid, 1, 1, '', srcMAC, dstMAC )
Jon Hall2bb3e212017-05-24 17:07:25 -0700317 if id is None:
You Wang7a27f3a2016-07-05 10:12:27 -0700318 main.log.warn( self.typeString + " - add point intent failed" )
319 return EventStates().FAIL
320 with main.variableLock:
321 newPointIntent = PointIntent( id, self.deviceA, self.deviceB )
322 if self.deviceA.isDown() or self.deviceB.isDown() or self.deviceA.isRemoved() or self.deviceB.isRemoved():
323 newPointIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700324 else:
325 newPointIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700326 main.intents.append( newPointIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700327 return EventStates().PASS
328 except Exception:
329 main.log.warn( "Caught exception, aborting event" )
330 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800331
Jon Hall2bb3e212017-05-24 17:07:25 -0700332
You Wangdb927a52016-02-26 11:03:28 -0800333class DelPointIntent( PointIntentEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700334
You Wangdb927a52016-02-26 11:03:28 -0800335 """
336 Delete a point-to-point intent
337 """
338 def __init__( self ):
339 PointIntentEvent.__init__( self )
340 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700341 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800342
343 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700344 try:
Jon Hall2bb3e212017-05-24 17:07:25 -0700345 assert self.deviceA is not None and self.deviceB is not None
You Wang7a27f3a2016-07-05 10:12:27 -0700346 targetIntent = None
347 for intent in main.intents:
348 if not intent.type == 'INTENT_POINT':
349 continue
350 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
351 targetIntent = intent
352 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700353 if targetIntent is None:
You Wang7a27f3a2016-07-05 10:12:27 -0700354 main.log.warn( self.typeString + " - intent does not exist" )
355 return EventStates().FAIL
You Wang52163202016-07-14 16:37:15 -0700356 main.log.info( "Event recorded: {} {} {} {} {}".format( self.typeIndex, self.typeString, self.deviceA.name, self.deviceB.name, self.CLIIndex ) )
You Wang7a27f3a2016-07-05 10:12:27 -0700357 controller = main.controllers[ self.CLIIndex - 1 ]
358 with controller.CLILock:
359 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
Jon Hall2bb3e212017-05-24 17:07:25 -0700360 if result is None or result == main.FALSE:
You Wang7a27f3a2016-07-05 10:12:27 -0700361 main.log.warn( self.typeString + " - delete point intent failed" )
362 return EventStates().FAIL
363 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700364 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700365 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700366 return EventStates().PASS
367 except Exception:
368 main.log.warn( "Caught exception, aborting event" )
369 return EventStates().ABORT