blob: 8ec62a1c33a0b9744ad4e2f5bfae6b21e7a9520e [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:
22 main.log.info( "%s - starting event" % ( self.typeString ) )
23 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
87 with main.mininetLock:
You Wang221db322016-06-03 15:45:52 -070088 '''
You Wangdb927a52016-02-26 11:03:28 -080089 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
90 END2=self.linkA.deviceB.name,
91 OPTION="down")
You Wang221db322016-06-03 15:45:52 -070092 '''
93 result = main.Mininet1.delLink( self.linkA.deviceA.name,
94 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -080095 if not result:
96 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
97 return EventStates().FAIL
98 with main.variableLock:
99 self.linkA.bringDown()
100 self.linkB.bringDown()
101 return EventStates().PASS
102
103class LinkUp( LinkEvent ):
104 """
105 Generate a link up event giving the two ends of the link
106 """
107 def __init__( self ):
108 LinkEvent.__init__( self )
109 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
110 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
111
112 def startLinkEvent( self ):
113 assert self.linkA != None and self.linkB != None
114 with main.variableLock:
115 if self.linkA.isUp() or self.linkB.isUp():
116 main.log.warn( "Link Up - link already up" )
117 return EventStates().ABORT
118 if self.linkA.isRemoved() or self.linkB.isRemoved():
119 main.log.warn( "Link Up - link has been removed" )
120 return EventStates().ABORT
121 with main.mininetLock:
You Wang221db322016-06-03 15:45:52 -0700122 '''
You Wangdb927a52016-02-26 11:03:28 -0800123 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
124 END2=self.linkA.deviceB.name,
125 OPTION="up")
You Wang221db322016-06-03 15:45:52 -0700126 '''
127 result = main.Mininet1.addLink( self.linkA.deviceA.name,
128 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800129 if not result:
130 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
131 return EventStates().FAIL
132 with main.variableLock:
133 self.linkA.bringUp()
134 self.linkB.bringUp()
135 return EventStates().PASS
136
137class DeviceEvent( Event ):
138 def __init__( self ):
139 Event.__init__( self )
140 self.device = None
141
142 def startDeviceEvent( self ):
143 return EventStates().PASS
144
145 def startEvent( self, args ):
146 """
147 args are the names of the device, e.g. 's1'
148 """
149 with self.eventLock:
150 main.log.info( "%s - starting event" % ( self.typeString ) )
151 if len( args ) < 1:
152 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
153 return EventStates().ABORT
154 elif len( args ) > 1:
155 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
156 return EventStates().ABORT
157 if args[ 0 ] == 'random':
158 import random
159 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
You Wang221db322016-06-03 15:45:52 -0700160 with main.mininetLock:
161 switchRandom = main.Mininet1.getSwitchRandom()
162 if switchRandom == None:
163 main.log.warn( "No switch available, aborting event" )
164 return EventStates().ABORT
165 args[ 0 ] = switchRandom
You Wangdb927a52016-02-26 11:03:28 -0800166 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
167 with main.variableLock:
168 removedDevices = []
169 for device in main.devices:
170 if device.isRemoved():
171 removedDevices.append( device )
172 if len( removedDevices ) == 0:
173 main.log.warn( "None of the devices are removed, aborting event" )
174 return EventStates().ABORT
175 deviceList = random.sample( removedDevices, 1 )
176 self.device = deviceList[ 0 ]
You Wang221db322016-06-03 15:45:52 -0700177 if self.device == None:
You Wangdb927a52016-02-26 11:03:28 -0800178 for device in main.devices:
179 if device.name == args[ 0 ]:
180 self.device = device
181 if self.device == None:
182 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
183 return EventStates().ABORT
184 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
185 return self.startDeviceEvent()
186
187class DeviceDown( DeviceEvent ):
188 """
189 Generate a device down event (which actually removes this device for now) giving its name
190 """
191 def __init__( self ):
192 DeviceEvent.__init__( self )
193 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
194 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
195
196 def startDeviceEvent( self ):
197 assert self.device != None
198 with main.variableLock:
199 if self.device.isRemoved():
200 main.log.warn( "Device Down - device has been removed" )
201 return EventStates().ABORT
202 with main.mininetLock:
203 result = main.Mininet1.delSwitch( self.device.name )
204 if not result:
205 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
206 return EventStates().FAIL
207 with main.variableLock:
208 self.device.setRemoved()
209 for link in self.device.outgoingLinks:
210 link.setRemoved()
211 link.backwardLink.setRemoved()
212 for host in self.device.hosts:
213 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700214 for intent in main.intents:
215 if intent.deviceA == self.device or intent.deviceB == self.device:
216 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800217 return EventStates().PASS
218
219class DeviceUp( DeviceEvent ):
220 """
221 Generate a device up event (which re-adds this device in case the device is removed) giving its name
222 """
223 def __init__( self ):
224 DeviceEvent.__init__( self )
225 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
226 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
227
228 def startDeviceEvent( self ):
229 assert self.device != None
230 with main.variableLock:
231 if self.device.isUp():
232 main.log.warn( "Device Up - device already up" )
233 return EventStates().ABORT
234 # Re-add the device
235 with main.mininetLock:
236 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[3:] )
237 if not result:
238 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
239 return EventStates().FAIL
240 with main.variableLock:
241 self.device.bringUp()
242 # Re-add links
243 # We add host-device links first since we did the same in mininet topology file
244 # TODO: a more rubust way is to add links according to the port info of the device
245 for host in self.device.hosts:
246 # Add host-device link
247 with main.mininetLock:
248 result = main.Mininet1.addLink( self.device.name, host.name )
249 if not result:
250 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
251 return EventStates().FAIL
252 for link in self.device.outgoingLinks:
253 neighbor = link.deviceB
254 # Skip bringing up any link that connecting this device to a removed neighbor
255 if neighbor.isRemoved():
256 continue
257 with main.mininetLock:
258 result = main.Mininet1.addLink( self.device.name, neighbor.name )
259 if not result:
260 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
261 return EventStates().FAIL
262 with main.variableLock:
263 link.bringUp()
264 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700265 for intent in main.intents:
266 if intent.isFailed():
267 if intent.deviceA == self.device and intent.deviceB.isUp() or\
268 intent.deviceB == self.device and intent.deviceA.isUp():
269 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800270 # Re-assign mastership for the device
271 with main.mininetLock:
272 main.Mininet1.assignSwController( sw=self.device.name, ip=main.onosIPs )
273 # Re-discover hosts
274 for host in self.device.hosts:
275 correspondent = None
276 for h in main.hosts:
277 if h.isUp() and h != host:
278 correspondent = h
279 break
280 if correspondent == None:
281 with main.mininetLock:
282 main.Mininet1.pingall()
283 if main.enableIPv6:
284 main.Mininet1.pingall( protocol="IPv6" )
285 else:
286 ipv4Addr = None
287 ipv6Addr = None
288 for ipAddress in correspondent.ipAddresses:
289 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ) and ipv6Addr == None:
290 ipv6Addr = ipAddress
291 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ) and ipv4Addr == None:
292 ipv4Addr = ipAddress
293 assert ipv4Addr != None
294 host.handle.pingHostSetAlternative( [ ipv4Addr ], 1 )
295 if main.enableIPv6:
296 assert ipv6Addr != None
297 host.handle.pingHostSetAlternative( [ ipv6Addr ], 1, True )
298 with main.variableLock:
299 host.bringUp()
300 return EventStates().PASS