blob: a601c42233a31f7514cbbf03512314369882053c [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
Jon Hall2bb3e212017-05-24 17:07:25 -07008
You Wangdb927a52016-02-26 11:03:28 -08009class LinkEvent( 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 self.linkA = None
14 self.linkB = None
15
16 def startLinkEvent( self ):
17 return EventStates().PASS
18
19 def startEvent( self, args ):
20 """
Jon Hall2bb3e212017-05-24 17:07:25 -070021 args are the names of the two link ends, e.g. [ 's1', 's2' ]
You Wangdb927a52016-02-26 11:03:28 -080022 """
23 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070024 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080025 if len( args ) < 2:
26 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
27 return EventStates().ABORT
28 elif len( args ) > 2:
29 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
30 return EventStates().ABORT
31 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
You Wangdb927a52016-02-26 11:03:28 -080032 if self.typeIndex == EventType().NETWORK_LINK_DOWN:
You Wang221db322016-06-03 15:45:52 -070033 with main.mininetLock:
34 linkRandom = main.Mininet1.getLinkRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -070035 if linkRandom is None:
You Wang221db322016-06-03 15:45:52 -070036 main.log.warn( "No link available, aborting event" )
37 return EventStates().ABORT
38 args[ 0 ] = linkRandom[ 0 ]
39 args[ 1 ] = linkRandom[ 1 ]
You Wangdb927a52016-02-26 11:03:28 -080040 elif self.typeIndex == EventType().NETWORK_LINK_UP:
You Wang221db322016-06-03 15:45:52 -070041 import random
You Wangdb927a52016-02-26 11:03:28 -080042 with main.variableLock:
43 downLinks = []
44 for link in main.links:
45 if link.isDown():
46 downLinks.append( link )
47 if len( downLinks ) == 0:
48 main.log.warn( "None of the links are in 'down' state, aborting event" )
49 return EventStates().ABORT
50 linkList = random.sample( downLinks, 1 )
51 self.linkA = linkList[ 0 ]
52 self.linkB = linkList[ 0 ].backwardLink
53 elif args[ 0 ] == args[ 1 ]:
54 main.log.warn( "%s - invalid arguments: %s" % ( self.typeString, args ) )
55 return EventStates().ABORT
Jon Hall2bb3e212017-05-24 17:07:25 -070056 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080057 for link in main.links:
58 if link.deviceA.name == args[ 0 ] and link.deviceB.name == args[ 1 ]:
59 self.linkA = link
60 elif link.deviceA.name == args[ 1 ] and link.deviceB.name == args[ 0 ]:
61 self.linkB = link
Jon Hall2bb3e212017-05-24 17:07:25 -070062 if self.linkA is not None and self.linkB is not None:
You Wangdb927a52016-02-26 11:03:28 -080063 break
Jon Hall2bb3e212017-05-24 17:07:25 -070064 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080065 main.log.warn( "Bidirectional link %s - %s does not exist: " % ( args[ 0 ], args[ 1 ] ) )
66 return EventStates().ABORT
67 main.log.debug( "%s - %s" % ( self.typeString, self.linkA ) )
68 return self.startLinkEvent()
69
Jon Hall2bb3e212017-05-24 17:07:25 -070070
You Wangdb927a52016-02-26 11:03:28 -080071class LinkDown( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070072
You Wangdb927a52016-02-26 11:03:28 -080073 """
74 Generate a link down event giving the two ends of the link
75 """
76 def __init__( self ):
77 LinkEvent.__init__( self )
78 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
79 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
80
81 def startLinkEvent( self ):
82 # TODO: do we need to handle a unidirectional link?
Jon Hall2bb3e212017-05-24 17:07:25 -070083 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -080084 with main.variableLock:
85 if self.linkA.isDown() or self.linkB.isDown():
86 main.log.warn( "Link Down - link already down" )
87 return EventStates().ABORT
88 elif self.linkA.isRemoved() or self.linkB.isRemoved():
89 main.log.warn( "Link Down - link has been removed" )
90 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -070091 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 -080092 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -070093 """
You Wangdb927a52016-02-26 11:03:28 -080094 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
95 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -070096 OPTION="down" )
97 """
You Wang221db322016-06-03 15:45:52 -070098 result = main.Mininet1.delLink( self.linkA.deviceA.name,
99 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800100 if not result:
101 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
102 return EventStates().FAIL
103 with main.variableLock:
104 self.linkA.bringDown()
105 self.linkB.bringDown()
106 return EventStates().PASS
107
Jon Hall2bb3e212017-05-24 17:07:25 -0700108
You Wangdb927a52016-02-26 11:03:28 -0800109class LinkUp( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700110
You Wangdb927a52016-02-26 11:03:28 -0800111 """
112 Generate a link up event giving the two ends of the link
113 """
114 def __init__( self ):
115 LinkEvent.__init__( self )
116 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
117 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
118
119 def startLinkEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700120 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -0800121 with main.variableLock:
122 if self.linkA.isUp() or self.linkB.isUp():
123 main.log.warn( "Link Up - link already up" )
124 return EventStates().ABORT
125 if self.linkA.isRemoved() or self.linkB.isRemoved():
126 main.log.warn( "Link Up - link has been removed" )
127 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700128 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 -0800129 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700130 """
You Wangdb927a52016-02-26 11:03:28 -0800131 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
132 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -0700133 OPTION="up" )
134 """
You Wang221db322016-06-03 15:45:52 -0700135 result = main.Mininet1.addLink( self.linkA.deviceA.name,
136 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800137 if not result:
138 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
139 return EventStates().FAIL
140 with main.variableLock:
141 self.linkA.bringUp()
142 self.linkB.bringUp()
143 return EventStates().PASS
144
Jon Hall2bb3e212017-05-24 17:07:25 -0700145
You Wangdb927a52016-02-26 11:03:28 -0800146class DeviceEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700147
You Wangdb927a52016-02-26 11:03:28 -0800148 def __init__( self ):
149 Event.__init__( self )
150 self.device = None
151
152 def startDeviceEvent( self ):
153 return EventStates().PASS
154
155 def startEvent( self, args ):
156 """
157 args are the names of the device, e.g. 's1'
158 """
159 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -0700160 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -0800161 if len( args ) < 1:
162 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
163 return EventStates().ABORT
164 elif len( args ) > 1:
165 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
166 return EventStates().ABORT
167 if args[ 0 ] == 'random':
168 import random
169 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
You Wang221db322016-06-03 15:45:52 -0700170 with main.mininetLock:
171 switchRandom = main.Mininet1.getSwitchRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -0700172 if switchRandom is None:
You Wang221db322016-06-03 15:45:52 -0700173 main.log.warn( "No switch available, aborting event" )
174 return EventStates().ABORT
175 args[ 0 ] = switchRandom
You Wangdb927a52016-02-26 11:03:28 -0800176 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
177 with main.variableLock:
178 removedDevices = []
179 for device in main.devices:
180 if device.isRemoved():
181 removedDevices.append( device )
182 if len( removedDevices ) == 0:
183 main.log.warn( "None of the devices are removed, aborting event" )
184 return EventStates().ABORT
185 deviceList = random.sample( removedDevices, 1 )
186 self.device = deviceList[ 0 ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700187 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800188 for device in main.devices:
189 if device.name == args[ 0 ]:
190 self.device = device
Jon Hall2bb3e212017-05-24 17:07:25 -0700191 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800192 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
193 return EventStates().ABORT
194 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
195 return self.startDeviceEvent()
196
Jon Hall2bb3e212017-05-24 17:07:25 -0700197
You Wangdb927a52016-02-26 11:03:28 -0800198class DeviceDown( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700199
You Wangdb927a52016-02-26 11:03:28 -0800200 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700201 Generate a device down event ( which actually removes this device for now ) giving its name
You Wangdb927a52016-02-26 11:03:28 -0800202 """
203 def __init__( self ):
204 DeviceEvent.__init__( self )
205 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
206 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
207
208 def startDeviceEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700209 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800210 with main.variableLock:
211 if self.device.isRemoved():
212 main.log.warn( "Device Down - device has been removed" )
213 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700214 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800215 with main.mininetLock:
216 result = main.Mininet1.delSwitch( self.device.name )
217 if not result:
218 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
219 return EventStates().FAIL
220 with main.variableLock:
221 self.device.setRemoved()
222 for link in self.device.outgoingLinks:
223 link.setRemoved()
224 link.backwardLink.setRemoved()
225 for host in self.device.hosts:
226 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700227 for intent in main.intents:
228 if intent.deviceA == self.device or intent.deviceB == self.device:
229 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800230 return EventStates().PASS
231
Jon Hall2bb3e212017-05-24 17:07:25 -0700232
You Wangdb927a52016-02-26 11:03:28 -0800233class DeviceUp( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700234
You Wangdb927a52016-02-26 11:03:28 -0800235 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700236 Generate a device up event ( which re-adds this device in case the device is removed ) giving its name
You Wangdb927a52016-02-26 11:03:28 -0800237 """
238 def __init__( self ):
239 DeviceEvent.__init__( self )
240 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
241 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
242
243 def startDeviceEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700244 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800245 with main.variableLock:
246 if self.device.isUp():
247 main.log.warn( "Device Up - device already up" )
248 return EventStates().ABORT
249 # Re-add the device
You Wang52163202016-07-14 16:37:15 -0700250 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800251 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700252 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[ 3: ] )
You Wangdb927a52016-02-26 11:03:28 -0800253 if not result:
254 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
255 return EventStates().FAIL
256 with main.variableLock:
257 self.device.bringUp()
258 # Re-add links
259 # We add host-device links first since we did the same in mininet topology file
260 # TODO: a more rubust way is to add links according to the port info of the device
261 for host in self.device.hosts:
262 # Add host-device link
263 with main.mininetLock:
264 result = main.Mininet1.addLink( self.device.name, host.name )
265 if not result:
266 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
267 return EventStates().FAIL
268 for link in self.device.outgoingLinks:
269 neighbor = link.deviceB
270 # Skip bringing up any link that connecting this device to a removed neighbor
271 if neighbor.isRemoved():
272 continue
273 with main.mininetLock:
274 result = main.Mininet1.addLink( self.device.name, neighbor.name )
275 if not result:
276 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
277 return EventStates().FAIL
278 with main.variableLock:
279 link.bringUp()
280 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700281 for intent in main.intents:
282 if intent.isFailed():
283 if intent.deviceA == self.device and intent.deviceB.isUp() or\
Jon Hall2bb3e212017-05-24 17:07:25 -0700284 intent.deviceB == self.device and intent.deviceA.isUp():
You Wang2b687c02016-05-13 17:01:31 -0700285 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800286 # Re-assign mastership for the device
287 with main.mininetLock:
You Wang2d32ef42017-03-03 14:09:44 -0800288 main.Mininet1.assignSwController( sw=self.device.name, ip=main.ONOSip )
You Wangdb927a52016-02-26 11:03:28 -0800289 # Re-discover hosts
290 for host in self.device.hosts:
291 correspondent = None
292 for h in main.hosts:
293 if h.isUp() and h != host:
294 correspondent = h
295 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700296 if correspondent is None:
You Wangdb927a52016-02-26 11:03:28 -0800297 with main.mininetLock:
298 main.Mininet1.pingall()
299 if main.enableIPv6:
300 main.Mininet1.pingall( protocol="IPv6" )
301 else:
302 ipv4Addr = None
303 ipv6Addr = None
304 for ipAddress in correspondent.ipAddresses:
Jon Hall2bb3e212017-05-24 17:07:25 -0700305 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ) and ipv6Addr is None:
You Wangdb927a52016-02-26 11:03:28 -0800306 ipv6Addr = ipAddress
Jon Hall2bb3e212017-05-24 17:07:25 -0700307 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ) and ipv4Addr is None:
You Wangdb927a52016-02-26 11:03:28 -0800308 ipv4Addr = ipAddress
Jon Hall2bb3e212017-05-24 17:07:25 -0700309 assert ipv4Addr is not None
You Wangdb927a52016-02-26 11:03:28 -0800310 host.handle.pingHostSetAlternative( [ ipv4Addr ], 1 )
311 if main.enableIPv6:
Jon Hall2bb3e212017-05-24 17:07:25 -0700312 assert ipv6Addr is not None
You Wangdb927a52016-02-26 11:03:28 -0800313 host.handle.pingHostSetAlternative( [ ipv6Addr ], 1, True )
314 with main.variableLock:
315 host.bringUp()
316 return EventStates().PASS