blob: 07c8cb6d376f43bb62303e570719aa51f614fdb6 [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 Wang59dfeb62016-07-14 09:47:33 -070074 try:
75 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
76 if self.typeIndex == EventType().APP_INTENT_HOST_ADD:
77 hostPairRandom = self.getRandomHostPair( connected=False )
78 if hostPairRandom == None:
79 main.log.warn( "All host pairs are connected, aborting event" )
80 return EventStates().ABORT
81 self.hostA = hostPairRandom[ 0 ]
82 self.hostB = hostPairRandom[ 1 ]
83 elif self.typeIndex == EventType().APP_INTENT_HOST_DEL:
84 intent = self.getRandomIntentByType( 'INTENT_HOST' )
85 if intent == None:
86 main.log.warn( "No host intent for deletion, aborting event" )
87 return EventStates().ABORT
88 self.hostA = intent.hostA
89 self.hostB = intent.hostB
90 elif args[ 0 ] == args[ 1 ]:
91 main.log.warn( "%s - invalid argument: %s, %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
You Wangdb927a52016-02-26 11:03:28 -080092 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -070093 else:
94 for host in main.hosts:
95 if host.name == args[ 0 ]:
96 self.hostA = host
97 elif host.name == args[ 1 ]:
98 self.hostB = host
99 if self.hostA != None and self.hostB != None:
100 break
101 if self.hostA == None:
102 main.log.warn( "Host %s does not exist: " % ( args[ 0 ] ) )
103 return EventStates().ABORT
104 if self.hostB == None:
105 main.log.warn( "Host %s does not exist: " % ( args[ 1 ] ) )
106 return EventStates().ABORT
107 index = int( args[ 2 ] )
108 if index < 1 or index > int( main.numCtrls ):
109 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
You Wangdb927a52016-02-26 11:03:28 -0800110 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -0700111 if not main.controllers[ index - 1 ].isUp():
112 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
113 return EventStates().ABORT
114 self.CLIIndex = index
115 return self.startHostIntentEvent()
116 except Exception:
117 main.log.warn( "Caught exception, aborting event" )
You Wang7a27f3a2016-07-05 10:12:27 -0700118 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800119
120class AddHostIntent( HostIntentEvent ):
121 """
122 Add a host-to-host intent (bidirectional)
123 """
124 def __init__( self ):
125 HostIntentEvent.__init__( self )
126 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
127 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
128
129 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700130 try:
131 assert self.hostA != None and self.hostB != None
132 # Check whether there already exists some intent for the host pair
133 # For now we should avoid installing overlapping intents
134 for intent in main.intents:
135 if not intent.type == 'INTENT_HOST':
136 continue
137 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
138 intent.hostB == self.hostA and intent.hostA == self.hostB:
139 main.log.warn( self.typeString + " - find an exiting intent for the host pair, abort installation" )
140 return EventStates().ABORT
141 controller = main.controllers[ self.CLIIndex - 1 ]
142 with controller.CLILock:
143 id = controller.CLI.addHostIntent( self.hostA.id, self.hostB.id )
144 if id == None:
145 main.log.warn( self.typeString + " - add host intent failed" )
146 return EventStates().FAIL
147 with main.variableLock:
148 newHostIntent = HostIntent( id, self.hostA, self.hostB )
149 if self.hostA.isDown() or self.hostA.isRemoved() or self.hostB.isDown() or self.hostB.isRemoved():
150 newHostIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700151 else:
152 newHostIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700153 main.intents.append( newHostIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700154 return EventStates().PASS
155 except Exception:
156 main.log.warn( "Caught exception, aborting event" )
157 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800158
159class DelHostIntent( HostIntentEvent ):
160 """
161 Delete a host-to-host intent (bidirectional)
162 """
163 def __init__( self ):
164 HostIntentEvent.__init__( self )
165 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
166 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
167
168 def startHostIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700169 try:
170 assert self.hostA != None and self.hostB != None
171 targetIntent = None
172 for intent in main.intents:
173 if not intent.type == 'INTENT_HOST':
174 continue
175 if intent.hostA == self.hostA and intent.hostB == self.hostB or\
176 intent.hostB == self.hostA and intent.hostA == self.hostB:
177 targetIntent = intent
178 break
179 if targetIntent == None:
180 main.log.warn( self.typeString + " - intent does not exist" )
181 return EventStates().FAIL
182 controller = main.controllers[ self.CLIIndex - 1 ]
183 with controller.CLILock:
184 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
185 if result == None or result == main.FALSE:
186 main.log.warn( self.typeString + " - delete host intent failed" )
187 return EventStates().FAIL
188 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700189 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700190 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700191 return EventStates().PASS
192 except Exception:
193 main.log.warn( "Caught exception, aborting event" )
194 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800195
196class PointIntentEvent( IntentEvent ):
197 def __init__( self ):
198 IntentEvent.__init__( self )
199 self.deviceA = None
200 self.deviceB = None
201
202 def startPointIntentEvent( self ):
203 return EventStates().PASS
204
205 def startEvent( self, args ):
206 with self.eventLock:
207 main.log.info( "%s - starting event" % ( self.typeString ) )
208 if self.typeIndex == EventType().APP_INTENT_POINT_ADD or self.typeIndex == EventType().APP_INTENT_POINT_DEL:
209 if len( args ) < 3:
210 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
211 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700212 elif len( args ) > 4:
You Wangdb927a52016-02-26 11:03:28 -0800213 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
214 return EventStates().ABORT
You Wang59dfeb62016-07-14 09:47:33 -0700215 try:
216 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
217 if self.typeIndex == EventType().APP_INTENT_POINT_ADD:
218 hostPairRandom = self.getRandomHostPair( connected=False )
219 if hostPairRandom == None:
220 main.log.warn( "All host pairs are connected, aborting event" )
221 return EventStates().ABORT
222 self.deviceA = hostPairRandom[ 0 ].device
223 self.deviceB = hostPairRandom[ 1 ].device
224 elif self.typeIndex == EventType().APP_INTENT_POINT_DEL:
225 intent = self.getRandomIntentByType( 'INTENT_POINT' )
226 if intent == None:
227 main.log.warn( "No point intent for deletion, aborting event" )
228 return EventStates().ABORT
229 self.deviceA = intent.deviceA
230 self.deviceB = intent.deviceB
231 elif args[ 0 ] == args[ 1 ]:
232 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, args[ 0 ], args[ 1 ] ) )
You Wangdb927a52016-02-26 11:03:28 -0800233 return EventStates().ABORT
You Wang7a27f3a2016-07-05 10:12:27 -0700234 else:
You Wang59dfeb62016-07-14 09:47:33 -0700235 for device in main.devices:
236 if device.name == args[ 0 ]:
237 self.deviceA = device
238 elif device.name == args[ 1 ]:
239 self.deviceB = device
240 if self.deviceA != None and self.deviceB != None:
241 break
242 if self.deviceA == None:
243 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
244 return EventStates().ABORT
245 if self.deviceB == None:
246 main.log.warn( "Device %s does not exist: " % ( args[ 1 ] ) )
247 return EventStates().ABORT
248 index = int( args[ 2 ] )
249 if index < 1 or index > int( main.numCtrls ):
250 main.log.warn( "%s - invalid argument: %s" % ( self.typeString, index ) )
251 return EventStates().ABORT
252 if not main.controllers[ index - 1 ].isUp():
253 main.log.warn( self.typeString + " - invalid argument: onos %s is down" % ( controller.index ) )
254 return EventStates().ABORT
255 self.CLIIndex = index
256 if len( args ) == 4 and args[ 3 ] == 'bidirectional':
257 # Install point intents for both directions
258 resultA = self.startPointIntentEvent()
259 [ self.deviceA, self.deviceB ] = [ self.deviceB, self.deviceA ]
260 resultB = self.startPointIntentEvent()
261 if resultA == EventStates().PASS and resultB == EventStates().PASS:
262 return EventStates().PASS
263 else:
264 return EventStates().FAIL
265 else:
266 return self.startPointIntentEvent()
267 except Exception:
268 main.log.warn( "Caught exception, aborting event" )
269 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800270
271class AddPointIntent( PointIntentEvent ):
272 """
273 Add a point-to-point intent
274 """
275 def __init__( self ):
276 PointIntentEvent.__init__( self )
277 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
278 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
279
280 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700281 try:
282 assert self.deviceA != None and self.deviceB != None
283 controller = main.controllers[ self.CLIIndex - 1 ]
You Wang59dfeb62016-07-14 09:47:33 -0700284 # TODO: support multiple hosts under one device
You Wang7a27f3a2016-07-05 10:12:27 -0700285 # Check whether there already exists some intent for the device pair
286 # For now we should avoid installing overlapping intents
287 for intent in main.intents:
288 if not intent.type == 'INTENT_POINT':
289 continue
290 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
291 main.log.warn( self.typeString + " - find an exiting intent for the device pair, abort installation" )
292 return EventStates().ABORT
293 controller = main.controllers[ self.CLIIndex - 1 ]
294 with controller.CLILock:
You Wang7a27f3a2016-07-05 10:12:27 -0700295 srcMAC = ""
296 dstMAC = ""
297 if len( self.deviceA.hosts ) > 0:
298 srcMAC = self.deviceA.hosts[ 0 ].mac
299 if len( self.deviceB.hosts ) > 0:
300 dstMAC = self.deviceB.hosts[ 0 ].mac
You Wang59dfeb62016-07-14 09:47:33 -0700301 id = controller.CLI.addPointIntent( self.deviceA.dpid, self.deviceB.dpid, 1, 1, '', srcMAC, dstMAC )
You Wang7a27f3a2016-07-05 10:12:27 -0700302 if id == None:
303 main.log.warn( self.typeString + " - add point intent failed" )
304 return EventStates().FAIL
305 with main.variableLock:
306 newPointIntent = PointIntent( id, self.deviceA, self.deviceB )
307 if self.deviceA.isDown() or self.deviceB.isDown() or self.deviceA.isRemoved() or self.deviceB.isRemoved():
308 newPointIntent.setFailed()
You Wang56577c82016-07-12 10:49:23 -0700309 else:
310 newPointIntent.setInstalled()
You Wang7a27f3a2016-07-05 10:12:27 -0700311 main.intents.append( newPointIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700312 return EventStates().PASS
313 except Exception:
314 main.log.warn( "Caught exception, aborting event" )
315 return EventStates().ABORT
You Wangdb927a52016-02-26 11:03:28 -0800316
317class DelPointIntent( PointIntentEvent ):
318 """
319 Delete a point-to-point intent
320 """
321 def __init__( self ):
322 PointIntentEvent.__init__( self )
323 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
324 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
325
326 def startPointIntentEvent( self ):
You Wang7a27f3a2016-07-05 10:12:27 -0700327 try:
328 assert self.deviceA != None and self.deviceB != None
329 targetIntent = None
330 for intent in main.intents:
331 if not intent.type == 'INTENT_POINT':
332 continue
333 if intent.deviceA == self.deviceA and intent.deviceB == self.deviceB:
334 targetIntent = intent
335 break
336 if targetIntent == None:
337 main.log.warn( self.typeString + " - intent does not exist" )
338 return EventStates().FAIL
339 controller = main.controllers[ self.CLIIndex - 1 ]
340 with controller.CLILock:
341 result = controller.CLI.removeIntent( targetIntent.id, purge=True )
342 if result == None or result == main.FALSE:
343 main.log.warn( self.typeString + " - delete point intent failed" )
344 return EventStates().FAIL
345 with main.variableLock:
You Wang56577c82016-07-12 10:49:23 -0700346 targetIntent.setWithdrawn()
You Wang7a27f3a2016-07-05 10:12:27 -0700347 main.intents.remove( targetIntent )
You Wang7a27f3a2016-07-05 10:12:27 -0700348 return EventStates().PASS
349 except Exception:
350 main.log.warn( "Caught exception, aborting event" )
351 return EventStates().ABORT