blob: adcbfdc0273139e76c6eb5564b79818574843dac [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
8class IntentEvent( Event ):
9 def __init__( self ):
10 Event.__init__( self )
11 # The index of the ONOS CLI that is going to run the command
12 self.CLIIndex = 0
13
You Wang7a27f3a2016-07-05 10:12:27 -070014 def getRandomCorrespondent( self, hostA, connected=True ):
15 import random
16 if connected:
17 candidates = hostA.correspondents
18 else:
19 candidates = [ host for host in main.hosts if host not in hostA.correspondents and host != hostA ]
20 if len( candidates ) == 0:
21 return None
22 hostB = random.sample( candidates, 1 )[0]
23 return hostB
24
25 def getRandomHostPair( self, connected=True ):
26 import random
27 candidateDict = {}
28 with main.variableLock:
29 for host in main.hosts:
30 correspondent = self.getRandomCorrespondent( host, connected=connected )
31 if correspondent != None:
32 candidateDict[ host ] = correspondent
33 if candidateDict == {}:
34 return None
35 hostA = random.sample( candidateDict.keys(), 1 )[0]
36 hostB = candidateDict[ hostA ]
37 return [ hostA, hostB ]
38
39 def getIntentsByType( self, intentType ):
40 intents = []
41 with main.variableLock:
42 for intent in main.intents:
43 if intent.type == intentType:
44 intents.append( intent )
45 return intents
46
47 def getRandomIntentByType( self, intentType ):
48 import random
49 intents = self.getIntentsByType( intentType )
50 if len( intents ) == 0:
51 return None
52 intent = random.sample( intents, 1 )[ 0 ]
53 return intent
54
You Wangdb927a52016-02-26 11:03:28 -080055class HostIntentEvent( IntentEvent ):
56 def __init__( self ):
57 IntentEvent.__init__( self )
58 self.hostA = None
59 self.hostB = None
60
61 def startHostIntentEvent( self ):
62 return EventStates().PASS
63
64 def startEvent( self, args ):
65 with self.eventLock:
66 main.log.info( "%s - starting event" % ( self.typeString ) )
67 if self.typeIndex == EventType().APP_INTENT_HOST_ADD or self.typeIndex == EventType().APP_INTENT_HOST_DEL:
68 if len( args ) < 3:
69 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
70 return EventStates().ABORT
71 elif len( args ) > 3:
72 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
73 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -070074 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
75 if self.typeIndex == EventType().APP_INTENT_HOST_ADD:
76 hostPairRandom = self.getRandomHostPair( connected=False )
77 if hostPairRandom == None:
78 main.log.warn( "All host pairs are connected, aborting event" )
79 return EventStates().ABORT
80 self.hostA = hostPairRandom[ 0 ]
81 self.hostB = hostPairRandom[ 1 ]
82 elif self.typeIndex == EventType().APP_INTENT_HOST_DEL:
83 intent = self.getRandomIntentByType( 'INTENT_HOST' )
84 if intent == None:
85 main.log.warn( "No host intent for deletion, aborting event" )
86 return EventStates().ABORT
87 self.hostA = intent.hostA
88 self.hostB = intent.hostB
89 elif args[ 0 ] == args[ 1 ]:
90 main.log.warn( "%s - invalid argument: %s, %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
91 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -080092 else:
You Wangdb927a52016-02-26 11:03:28 -080093 for host in main.hosts:
94 if host.name == args[ 0 ]:
95 self.hostA = host
96 elif host.name == args[ 1 ]:
97 self.hostB = host
98 if self.hostA != None and self.hostB != None:
99 break
100 if self.hostA == None:
101 main.log.warn( "Host %s does not exist: " % ( args[ 0 ] ) )
102 return EventStates().ABORT
103 if self.hostB == None:
104 main.log.warn( "Host %s does not exist: " % ( args[ 1 ] ) )
105 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700106 index = int( args[ 2 ] )
107 if index < 1 or index > int( main.numCtrls ):
108 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
109 return EventStates().ABORT
110 if not main.controllers[ index - 1 ].isUp():
111 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
112 return EventStates().ABORT
113 self.CLIIndex = index
114 return self.startHostIntentEvent()
You Wangdb927a52016-02-26 11:03:28 -0800115
116class AddHostIntent( HostIntentEvent ):
117 """
118 Add a host-to-host intent (bidirectional)
119 """
120 def __init__( self ):
121 HostIntentEvent.__init__( self )
122 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
123 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
124
125 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700126 try:
127 assert self.hostA != None and self.hostB != None
128 # Check whether there already exists some intent for the host pair
129 # For now we should avoid installing overlapping intents
130 for intent in main.intents:
131 if not intent.type == 'INTENT_HOST':
132 continue
133 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
134 intent.hostB == self.hostA and intent.hostA == self.hostB:
135 main.log.warn( self.typeString + " - find an exiting intent for the host pair, abort installation" )
136 return EventStates().ABORT
137 controller = main.controllers[ self.CLIIndex - 1 ]
138 with controller.CLILock:
139 id = controller.CLI.addHostIntent( self.hostA.id, self.hostB.id )
140 if id == None:
141 main.log.warn( self.typeString + " - add host intent failed" )
142 return EventStates().FAIL
143 with main.variableLock:
144 newHostIntent = HostIntent( id, self.hostA, self.hostB )
145 if self.hostA.isDown() or self.hostA.isRemoved() or self.hostB.isDown() or self.hostB.isRemoved():
146 newHostIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700147 else:
148 newHostIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700149 main.intents.append( newHostIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700150 return EventStates().PASS
151 except Exception:
152 main.log.warn( "Caught exception, aborting event" )
153 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800154
155class DelHostIntent( HostIntentEvent ):
156 """
157 Delete a host-to-host intent (bidirectional)
158 """
159 def __init__( self ):
160 HostIntentEvent.__init__( self )
161 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
162 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
163
164 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700165 try:
166 assert self.hostA != None and self.hostB != None
167 targetIntent = None
168 for intent in main.intents:
169 if not intent.type == 'INTENT_HOST':
170 continue
171 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
172 intent.hostB == self.hostA and intent.hostA == self.hostB:
173 targetIntent = intent
174 break
175 if targetIntent == None:
176 main.log.warn( self.typeString + " - intent does not exist" )
177 return EventStates().FAIL
178 controller = main.controllers[ self.CLIIndex - 1 ]
179 with controller.CLILock:
180 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
181 if result == None or result == main.FALSE:
182 main.log.warn( self.typeString + " - delete host intent failed" )
183 return EventStates().FAIL
184 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700185 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700186 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700187 return EventStates().PASS
188 except Exception:
189 main.log.warn( "Caught exception, aborting event" )
190 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800191
192class PointIntentEvent( IntentEvent ):
193 def __init__( self ):
194 IntentEvent.__init__( self )
195 self.deviceA = None
196 self.deviceB = None
197
198 def startPointIntentEvent( self ):
199 return EventStates().PASS
200
201 def startEvent( self, args ):
202 with self.eventLock:
203 main.log.info( "%s - starting event" % ( self.typeString ) )
204 if self.typeIndex == EventType().APP_INTENT_POINT_ADD or self.typeIndex == EventType().APP_INTENT_POINT_DEL:
205 if len( args ) < 3:
206 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
207 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700208 elif len( args ) > 4:
You Wangdb927a52016-02-26 11:03:28 -0800209 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
210 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700211 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
212 if self.typeIndex == EventType().APP_INTENT_POINT_ADD:
213 hostPairRandom = self.getRandomHostPair( connected=False )
214 if hostPairRandom == None:
215 main.log.warn( "All host pairs are connected, aborting event" )
216 return EventStates().ABORT
217 self.deviceA = hostPairRandom[ 0 ].device
218 self.deviceB = hostPairRandom[ 1 ].device
219 elif self.typeIndex == EventType().APP_INTENT_POINT_DEL:
220 intent = self.getRandomIntentByType( 'INTENT_POINT' )
221 if intent == None:
222 main.log.warn( "No point intent for deletion, aborting event" )
223 return EventStates().ABORT
224 self.deviceA = intent.deviceA
225 self.deviceB = intent.deviceB
226 elif args[ 0 ] == args[ 1 ]:
227 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
228 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800229 else:
230 for device in main.devices:
231 if device.name == args[ 0 ]:
232 self.deviceA = device
233 elif device.name == args[ 1 ]:
234 self.deviceB = device
235 if self.deviceA != None and self.deviceB != None:
236 break
237 if self.deviceA == None:
238 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
239 return EventStates().ABORT
240 if self.deviceB == None:
241 main.log.warn( "Device %s does not exist: " % ( args[ 1 ] ) )
242 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700243 index = int( args[ 2 ] )
244 if index < 1 or index > int( main.numCtrls ):
245 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
246 return EventStates().ABORT
247 if not main.controllers[ index - 1 ].isUp():
248 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
249 return EventStates().ABORT
250 self.CLIIndex = index
251 if len( args ) == 4 and args[ 3 ] == 'bidirectional':
252 # Install point intents for both directions
253 resultA = self.startPointIntentEvent()
254 [ self.deviceA, self.deviceB ] = [ self.deviceB, self.deviceA ]
255 resultB = self.startPointIntentEvent()
256 if resultA == EventStates().PASS and resultB == EventStates().PASS:
257 return EventStates().PASS
258 else:
259 return EventStates().FAIL
260 else:
You Wangdb927a52016-02-26 11:03:28 -0800261 return self.startPointIntentEvent()
262
263class AddPointIntent( PointIntentEvent ):
264 """
265 Add a point-to-point intent
266 """
267 def __init__( self ):
268 PointIntentEvent.__init__( self )
269 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
270 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
271
272 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700273 try:
274 assert self.deviceA != None and self.deviceB != None
275 controller = main.controllers[ self.CLIIndex - 1 ]
276 # TODO: the following check only work when we use default port number for point intents
277 # Check whether there already exists some intent for the device pair
278 # For now we should avoid installing overlapping intents
279 for intent in main.intents:
280 if not intent.type == 'INTENT_POINT':
281 continue
282 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
283 main.log.warn( self.typeString + " - find an exiting intent for the device pair, abort installation" )
284 return EventStates().ABORT
285 controller = main.controllers[ self.CLIIndex - 1 ]
286 with controller.CLILock:
287 # TODO: handle the case that multiple hosts attach to one device
288 srcMAC = ""
289 dstMAC = ""
290 if len( self.deviceA.hosts ) > 0:
291 srcMAC = self.deviceA.hosts[ 0 ].mac
292 if len( self.deviceB.hosts ) > 0:
293 dstMAC = self.deviceB.hosts[ 0 ].mac
294 id = controller.CLI.addPointIntent( self.deviceA.dpid, self.deviceB.dpid,
295 1, 1, '', srcMAC, dstMAC )
296 if id == None:
297 main.log.warn( self.typeString + " - add point intent failed" )
298 return EventStates().FAIL
299 with main.variableLock:
300 newPointIntent = PointIntent( id, self.deviceA, self.deviceB )
301 if self.deviceA.isDown() or self.deviceB.isDown() or self.deviceA.isRemoved() or self.deviceB.isRemoved():
302 newPointIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700303 else:
304 newPointIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700305 main.intents.append( newPointIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700306 return EventStates().PASS
307 except Exception:
308 main.log.warn( "Caught exception, aborting event" )
309 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800310
311class DelPointIntent( PointIntentEvent ):
312 """
313 Delete a point-to-point intent
314 """
315 def __init__( self ):
316 PointIntentEvent.__init__( self )
317 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
318 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
319
320 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700321 try:
322 assert self.deviceA != None and self.deviceB != None
323 targetIntent = None
324 for intent in main.intents:
325 if not intent.type == 'INTENT_POINT':
326 continue
327 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
328 targetIntent = intent
329 break
330 if targetIntent == None:
331 main.log.warn( self.typeString + " - intent does not exist" )
332 return EventStates().FAIL
333 controller = main.controllers[ self.CLIIndex - 1 ]
334 with controller.CLILock:
335 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
336 if result == None or result == main.FALSE:
337 main.log.warn( self.typeString + " - delete point intent failed" )
338 return EventStates().FAIL
339 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700340 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700341 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700342 return EventStates().PASS
343 except Exception:
344 main.log.warn( "Caught exception, aborting event" )
345 return EventStates().ABORT