blob: ccab8a1a246b864f6326446f38ceb4a1659f73d1 [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
2This file contains classes for CHOTestMonkey that are related to network event
3Author: you@onlab.us
4"""
5from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
6from tests.CHOTestMonkey.dependencies.elements.NetworkElement import NetworkElement, Device, Host, Link
You Wangdb927a52016-02-26 11:03:28 -08007
8class LinkEvent( Event ):
9 def __init__( self ):
10 Event.__init__( self )
11 self.linkA = None
12 self.linkB = None
13
14 def startLinkEvent( self ):
15 return EventStates().PASS
16
17 def startEvent( self, args ):
18 """
19 args are the names of the two link ends, e.g. ['s1', 's2']
20 """
21 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070022 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080023 if len( args ) < 2:
24 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
25 return EventStates().ABORT
26 elif len( args ) > 2:
27 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
28 return EventStates().ABORT
29 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
You Wangdb927a52016-02-26 11:03:28 -080030 if self.typeIndex == EventType().NETWORK_LINK_DOWN:
You Wang221db322016-06-03 15:45:52 -070031 with main.mininetLock:
32 linkRandom = main.Mininet1.getLinkRandom()
33 if linkRandom == None:
34 main.log.warn( "No link available, aborting event" )
35 return EventStates().ABORT
36 args[ 0 ] = linkRandom[ 0 ]
37 args[ 1 ] = linkRandom[ 1 ]
You Wangdb927a52016-02-26 11:03:28 -080038 elif self.typeIndex == EventType().NETWORK_LINK_UP:
You Wang221db322016-06-03 15:45:52 -070039 import random
You Wangdb927a52016-02-26 11:03:28 -080040 with main.variableLock:
41 downLinks = []
42 for link in main.links:
43 if link.isDown():
44 downLinks.append( link )
45 if len( downLinks ) == 0:
46 main.log.warn( "None of the links are in 'down' state, aborting event" )
47 return EventStates().ABORT
48 linkList = random.sample( downLinks, 1 )
49 self.linkA = linkList[ 0 ]
50 self.linkB = linkList[ 0 ].backwardLink
51 elif args[ 0 ] == args[ 1 ]:
52 main.log.warn( "%s - invalid arguments: %s" % ( self.typeString, args ) )
53 return EventStates().ABORT
You Wang221db322016-06-03 15:45:52 -070054 if self.linkA == None or self.linkB == None:
You Wangdb927a52016-02-26 11:03:28 -080055 for link in main.links:
56 if link.deviceA.name == args[ 0 ] and link.deviceB.name == args[ 1 ]:
57 self.linkA = link
58 elif link.deviceA.name == args[ 1 ] and link.deviceB.name == args[ 0 ]:
59 self.linkB = link
60 if self.linkA != None and self.linkB != None:
61 break
62 if self.linkA == None or self.linkB == None:
63 main.log.warn( "Bidirectional link %s - %s does not exist: " % ( args[ 0 ], args[ 1 ] ) )
64 return EventStates().ABORT
65 main.log.debug( "%s - %s" % ( self.typeString, self.linkA ) )
66 return self.startLinkEvent()
67
68class LinkDown( LinkEvent ):
69 """
70 Generate a link down event giving the two ends of the link
71 """
72 def __init__( self ):
73 LinkEvent.__init__( self )
74 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
75 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
76
77 def startLinkEvent( self ):
78 # TODO: do we need to handle a unidirectional link?
79 assert self.linkA != None and self.linkB != None
80 with main.variableLock:
81 if self.linkA.isDown() or self.linkB.isDown():
82 main.log.warn( "Link Down - link already down" )
83 return EventStates().ABORT
84 elif self.linkA.isRemoved() or self.linkB.isRemoved():
85 main.log.warn( "Link Down - link has been removed" )
86 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -070087 main.log.info( "Event recorded: {} {} {} {}".format( self.typeIndex, self.typeString, self.linkA.deviceA.name, self.linkA.deviceB.name ) )
You Wangdb927a52016-02-26 11:03:28 -080088 with main.mininetLock:
You Wang221db322016-06-03 15:45:52 -070089 '''
You Wangdb927a52016-02-26 11:03:28 -080090 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
91 END2=self.linkA.deviceB.name,
92 OPTION="down")
You Wang221db322016-06-03 15:45:52 -070093 '''
94 result = main.Mininet1.delLink( self.linkA.deviceA.name,
95 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -080096 if not result:
97 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
98 return EventStates().FAIL
99 with main.variableLock:
100 self.linkA.bringDown()
101 self.linkB.bringDown()
102 return EventStates().PASS
103
104class LinkUp( LinkEvent ):
105 """
106 Generate a link up event giving the two ends of the link
107 """
108 def __init__( self ):
109 LinkEvent.__init__( self )
110 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
111 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
112
113 def startLinkEvent( self ):
114 assert self.linkA != None and self.linkB != None
115 with main.variableLock:
116 if self.linkA.isUp() or self.linkB.isUp():
117 main.log.warn( "Link Up - link already up" )
118 return EventStates().ABORT
119 if self.linkA.isRemoved() or self.linkB.isRemoved():
120 main.log.warn( "Link Up - link has been removed" )
121 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700122 main.log.info( "Event recorded: {} {} {} {}".format( self.typeIndex, self.typeString, self.linkA.deviceA.name, self.linkA.deviceB.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800123 with main.mininetLock:
You Wang221db322016-06-03 15:45:52 -0700124 '''
You Wangdb927a52016-02-26 11:03:28 -0800125 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
126 END2=self.linkA.deviceB.name,
127 OPTION="up")
You Wang221db322016-06-03 15:45:52 -0700128 '''
129 result = main.Mininet1.addLink( self.linkA.deviceA.name,
130 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800131 if not result:
132 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
133 return EventStates().FAIL
134 with main.variableLock:
135 self.linkA.bringUp()
136 self.linkB.bringUp()
137 return EventStates().PASS
138
139class DeviceEvent( Event ):
140 def __init__( self ):
141 Event.__init__( self )
142 self.device = None
143
144 def startDeviceEvent( self ):
145 return EventStates().PASS
146
147 def startEvent( self, args ):
148 """
149 args are the names of the device, e.g. 's1'
150 """
151 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -0700152 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -0800153 if len( args ) < 1:
154 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
155 return EventStates().ABORT
156 elif len( args ) > 1:
157 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
158 return EventStates().ABORT
159 if args[ 0 ] == 'random':
160 import random
161 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
You Wang221db322016-06-03 15:45:52 -0700162 with main.mininetLock:
163 switchRandom = main.Mininet1.getSwitchRandom()
164 if switchRandom == None:
165 main.log.warn( "No switch available, aborting event" )
166 return EventStates().ABORT
167 args[ 0 ] = switchRandom
You Wangdb927a52016-02-26 11:03:28 -0800168 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
169 with main.variableLock:
170 removedDevices = []
171 for device in main.devices:
172 if device.isRemoved():
173 removedDevices.append( device )
174 if len( removedDevices ) == 0:
175 main.log.warn( "None of the devices are removed, aborting event" )
176 return EventStates().ABORT
177 deviceList = random.sample( removedDevices, 1 )
178 self.device = deviceList[ 0 ]
You Wang221db322016-06-03 15:45:52 -0700179 if self.device == None:
You Wangdb927a52016-02-26 11:03:28 -0800180 for device in main.devices:
181 if device.name == args[ 0 ]:
182 self.device = device
183 if self.device == None:
184 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
185 return EventStates().ABORT
186 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
187 return self.startDeviceEvent()
188
189class DeviceDown( DeviceEvent ):
190 """
191 Generate a device down event (which actually removes this device for now) giving its name
192 """
193 def __init__( self ):
194 DeviceEvent.__init__( self )
195 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
196 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
197
198 def startDeviceEvent( self ):
199 assert self.device != None
200 with main.variableLock:
201 if self.device.isRemoved():
202 main.log.warn( "Device Down - device has been removed" )
203 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700204 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800205 with main.mininetLock:
206 result = main.Mininet1.delSwitch( self.device.name )
207 if not result:
208 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
209 return EventStates().FAIL
210 with main.variableLock:
211 self.device.setRemoved()
212 for link in self.device.outgoingLinks:
213 link.setRemoved()
214 link.backwardLink.setRemoved()
215 for host in self.device.hosts:
216 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700217 for intent in main.intents:
218 if intent.deviceA == self.device or intent.deviceB == self.device:
219 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800220 return EventStates().PASS
221
222class DeviceUp( DeviceEvent ):
223 """
224 Generate a device up event (which re-adds this device in case the device is removed) giving its name
225 """
226 def __init__( self ):
227 DeviceEvent.__init__( self )
228 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
229 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
230
231 def startDeviceEvent( self ):
232 assert self.device != None
233 with main.variableLock:
234 if self.device.isUp():
235 main.log.warn( "Device Up - device already up" )
236 return EventStates().ABORT
237 # Re-add the device
You Wang52163202016-07-14 16:37:15 -0700238 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800239 with main.mininetLock:
240 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[3:] )
241 if not result:
242 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
243 return EventStates().FAIL
244 with main.variableLock:
245 self.device.bringUp()
246 # Re-add links
247 # We add host-device links first since we did the same in mininet topology file
248 # TODO: a more rubust way is to add links according to the port info of the device
249 for host in self.device.hosts:
250 # Add host-device link
251 with main.mininetLock:
252 result = main.Mininet1.addLink( self.device.name, host.name )
253 if not result:
254 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
255 return EventStates().FAIL
256 for link in self.device.outgoingLinks:
257 neighbor = link.deviceB
258 # Skip bringing up any link that connecting this device to a removed neighbor
259 if neighbor.isRemoved():
260 continue
261 with main.mininetLock:
262 result = main.Mininet1.addLink( self.device.name, neighbor.name )
263 if not result:
264 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
265 return EventStates().FAIL
266 with main.variableLock:
267 link.bringUp()
268 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700269 for intent in main.intents:
270 if intent.isFailed():
271 if intent.deviceA == self.device and intent.deviceB.isUp() or\
272 intent.deviceB == self.device and intent.deviceA.isUp():
273 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800274 # Re-assign mastership for the device
275 with main.mininetLock:
276 main.Mininet1.assignSwController( sw=self.device.name, ip=main.onosIPs )
277 # Re-discover hosts
278 for host in self.device.hosts:
279 correspondent = None
280 for h in main.hosts:
281 if h.isUp() and h != host:
282 correspondent = h
283 break
284 if correspondent == None:
285 with main.mininetLock:
286 main.Mininet1.pingall()
287 if main.enableIPv6:
288 main.Mininet1.pingall( protocol="IPv6" )
289 else:
290 ipv4Addr = None
291 ipv6Addr = None
292 for ipAddress in correspondent.ipAddresses:
293 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ) and ipv6Addr == None:
294 ipv6Addr = ipAddress
295 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ) and ipv4Addr == None:
296 ipv4Addr = ipAddress
297 assert ipv4Addr != None
298 host.handle.pingHostSetAlternative( [ ipv4Addr ], 1 )
299 if main.enableIPv6:
300 assert ipv6Addr != None
301 host.handle.pingHostSetAlternative( [ ipv6Addr ], 1, True )
302 with main.variableLock:
303 host.bringUp()
304 return EventStates().PASS