blob: 82e60ed3bf2bcec59e206420d67607a8037d7386 [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07002Copyright 2016 Open Networking Foundation (ONF)
3
4Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
5the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
6or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
7
8 TestON is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 TestON is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with TestON. If not, see <http://www.gnu.org/licenses/>.
20"""
21
22"""
You Wangdb927a52016-02-26 11:03:28 -080023This file contains classes for CHOTestMonkey that are related to network event
24Author: you@onlab.us
25"""
26from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
27from tests.CHOTestMonkey.dependencies.elements.NetworkElement import NetworkElement, Device, Host, Link
You Wangdb927a52016-02-26 11:03:28 -080028
Jon Hall2bb3e212017-05-24 17:07:25 -070029
You Wangdb927a52016-02-26 11:03:28 -080030class LinkEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -070031
You Wangdb927a52016-02-26 11:03:28 -080032 def __init__( self ):
33 Event.__init__( self )
34 self.linkA = None
35 self.linkB = None
36
37 def startLinkEvent( self ):
38 return EventStates().PASS
39
40 def startEvent( self, args ):
41 """
Jon Hall2bb3e212017-05-24 17:07:25 -070042 args are the names of the two link ends, e.g. [ 's1', 's2' ]
You Wangdb927a52016-02-26 11:03:28 -080043 """
44 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070045 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080046 if len( args ) < 2:
47 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
48 return EventStates().ABORT
49 elif len( args ) > 2:
50 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
51 return EventStates().ABORT
52 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
You Wangdb927a52016-02-26 11:03:28 -080053 if self.typeIndex == EventType().NETWORK_LINK_DOWN:
You Wang221db322016-06-03 15:45:52 -070054 with main.mininetLock:
55 linkRandom = main.Mininet1.getLinkRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -070056 if linkRandom is None:
You Wang221db322016-06-03 15:45:52 -070057 main.log.warn( "No link available, aborting event" )
58 return EventStates().ABORT
59 args[ 0 ] = linkRandom[ 0 ]
60 args[ 1 ] = linkRandom[ 1 ]
You Wangdb927a52016-02-26 11:03:28 -080061 elif self.typeIndex == EventType().NETWORK_LINK_UP:
You Wang221db322016-06-03 15:45:52 -070062 import random
You Wangdb927a52016-02-26 11:03:28 -080063 with main.variableLock:
64 downLinks = []
65 for link in main.links:
66 if link.isDown():
67 downLinks.append( link )
68 if len( downLinks ) == 0:
69 main.log.warn( "None of the links are in 'down' state, aborting event" )
70 return EventStates().ABORT
71 linkList = random.sample( downLinks, 1 )
72 self.linkA = linkList[ 0 ]
73 self.linkB = linkList[ 0 ].backwardLink
74 elif args[ 0 ] == args[ 1 ]:
75 main.log.warn( "%s - invalid arguments: %s" % ( self.typeString, args ) )
76 return EventStates().ABORT
Jon Hall2bb3e212017-05-24 17:07:25 -070077 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080078 for link in main.links:
79 if link.deviceA.name == args[ 0 ] and link.deviceB.name == args[ 1 ]:
80 self.linkA = link
81 elif link.deviceA.name == args[ 1 ] and link.deviceB.name == args[ 0 ]:
82 self.linkB = link
Jon Hall2bb3e212017-05-24 17:07:25 -070083 if self.linkA is not None and self.linkB is not None:
You Wangdb927a52016-02-26 11:03:28 -080084 break
Jon Hall2bb3e212017-05-24 17:07:25 -070085 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080086 main.log.warn( "Bidirectional link %s - %s does not exist: " % ( args[ 0 ], args[ 1 ] ) )
87 return EventStates().ABORT
88 main.log.debug( "%s - %s" % ( self.typeString, self.linkA ) )
89 return self.startLinkEvent()
90
Jon Hall2bb3e212017-05-24 17:07:25 -070091
You Wangdb927a52016-02-26 11:03:28 -080092class LinkDown( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070093
You Wangdb927a52016-02-26 11:03:28 -080094 """
95 Generate a link down event giving the two ends of the link
96 """
97 def __init__( self ):
98 LinkEvent.__init__( self )
99 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
100 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
101
102 def startLinkEvent( self ):
103 # TODO: do we need to handle a unidirectional link?
Jon Hall2bb3e212017-05-24 17:07:25 -0700104 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -0800105 with main.variableLock:
106 if self.linkA.isDown() or self.linkB.isDown():
107 main.log.warn( "Link Down - link already down" )
108 return EventStates().ABORT
109 elif self.linkA.isRemoved() or self.linkB.isRemoved():
110 main.log.warn( "Link Down - link has been removed" )
111 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700112 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 -0800113 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700114 """
You Wangdb927a52016-02-26 11:03:28 -0800115 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
116 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -0700117 OPTION="down" )
118 """
You Wang221db322016-06-03 15:45:52 -0700119 result = main.Mininet1.delLink( self.linkA.deviceA.name,
120 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800121 if not result:
122 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
123 return EventStates().FAIL
124 with main.variableLock:
125 self.linkA.bringDown()
126 self.linkB.bringDown()
127 return EventStates().PASS
128
Jon Hall2bb3e212017-05-24 17:07:25 -0700129
You Wangdb927a52016-02-26 11:03:28 -0800130class LinkUp( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700131
You Wangdb927a52016-02-26 11:03:28 -0800132 """
133 Generate a link up event giving the two ends of the link
134 """
135 def __init__( self ):
136 LinkEvent.__init__( self )
137 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
138 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
139
140 def startLinkEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700141 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -0800142 with main.variableLock:
143 if self.linkA.isUp() or self.linkB.isUp():
144 main.log.warn( "Link Up - link already up" )
145 return EventStates().ABORT
146 if self.linkA.isRemoved() or self.linkB.isRemoved():
147 main.log.warn( "Link Up - link has been removed" )
148 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700149 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 -0800150 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700151 """
You Wangdb927a52016-02-26 11:03:28 -0800152 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
153 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -0700154 OPTION="up" )
155 """
You Wang221db322016-06-03 15:45:52 -0700156 result = main.Mininet1.addLink( self.linkA.deviceA.name,
157 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800158 if not result:
159 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
160 return EventStates().FAIL
161 with main.variableLock:
162 self.linkA.bringUp()
163 self.linkB.bringUp()
164 return EventStates().PASS
165
Jon Hall2bb3e212017-05-24 17:07:25 -0700166
You Wangdb927a52016-02-26 11:03:28 -0800167class DeviceEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700168
You Wangdb927a52016-02-26 11:03:28 -0800169 def __init__( self ):
170 Event.__init__( self )
171 self.device = None
172
173 def startDeviceEvent( self ):
174 return EventStates().PASS
175
176 def startEvent( self, args ):
177 """
178 args are the names of the device, e.g. 's1'
179 """
180 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -0700181 #main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -0800182 if len( args ) < 1:
183 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
184 return EventStates().ABORT
185 elif len( args ) > 1:
186 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
187 return EventStates().ABORT
188 if args[ 0 ] == 'random':
189 import random
190 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
You Wang221db322016-06-03 15:45:52 -0700191 with main.mininetLock:
192 switchRandom = main.Mininet1.getSwitchRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -0700193 if switchRandom is None:
You Wang221db322016-06-03 15:45:52 -0700194 main.log.warn( "No switch available, aborting event" )
195 return EventStates().ABORT
196 args[ 0 ] = switchRandom
You Wangdb927a52016-02-26 11:03:28 -0800197 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
198 with main.variableLock:
199 removedDevices = []
200 for device in main.devices:
201 if device.isRemoved():
202 removedDevices.append( device )
203 if len( removedDevices ) == 0:
204 main.log.warn( "None of the devices are removed, aborting event" )
205 return EventStates().ABORT
206 deviceList = random.sample( removedDevices, 1 )
207 self.device = deviceList[ 0 ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700208 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800209 for device in main.devices:
210 if device.name == args[ 0 ]:
211 self.device = device
Jon Hall2bb3e212017-05-24 17:07:25 -0700212 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800213 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
214 return EventStates().ABORT
215 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
216 return self.startDeviceEvent()
217
Jon Hall2bb3e212017-05-24 17:07:25 -0700218
You Wangdb927a52016-02-26 11:03:28 -0800219class DeviceDown( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700220
You Wangdb927a52016-02-26 11:03:28 -0800221 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700222 Generate a device down event ( which actually removes this device for now ) giving its name
You Wangdb927a52016-02-26 11:03:28 -0800223 """
224 def __init__( self ):
225 DeviceEvent.__init__( self )
226 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
227 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
228
229 def startDeviceEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700230 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800231 with main.variableLock:
232 if self.device.isRemoved():
233 main.log.warn( "Device Down - device has been removed" )
234 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700235 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800236 with main.mininetLock:
237 result = main.Mininet1.delSwitch( self.device.name )
238 if not result:
239 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
240 return EventStates().FAIL
241 with main.variableLock:
242 self.device.setRemoved()
243 for link in self.device.outgoingLinks:
244 link.setRemoved()
245 link.backwardLink.setRemoved()
246 for host in self.device.hosts:
247 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700248 for intent in main.intents:
249 if intent.deviceA == self.device or intent.deviceB == self.device:
250 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800251 return EventStates().PASS
252
Jon Hall2bb3e212017-05-24 17:07:25 -0700253
You Wangdb927a52016-02-26 11:03:28 -0800254class DeviceUp( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700255
You Wangdb927a52016-02-26 11:03:28 -0800256 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700257 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 -0800258 """
259 def __init__( self ):
260 DeviceEvent.__init__( self )
261 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
262 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
263
264 def startDeviceEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700265 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800266 with main.variableLock:
267 if self.device.isUp():
268 main.log.warn( "Device Up - device already up" )
269 return EventStates().ABORT
270 # Re-add the device
You Wang52163202016-07-14 16:37:15 -0700271 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800272 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700273 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[ 3: ] )
You Wangdb927a52016-02-26 11:03:28 -0800274 if not result:
275 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
276 return EventStates().FAIL
277 with main.variableLock:
278 self.device.bringUp()
279 # Re-add links
280 # We add host-device links first since we did the same in mininet topology file
281 # TODO: a more rubust way is to add links according to the port info of the device
282 for host in self.device.hosts:
283 # Add host-device link
284 with main.mininetLock:
285 result = main.Mininet1.addLink( self.device.name, host.name )
286 if not result:
287 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
288 return EventStates().FAIL
289 for link in self.device.outgoingLinks:
290 neighbor = link.deviceB
291 # Skip bringing up any link that connecting this device to a removed neighbor
292 if neighbor.isRemoved():
293 continue
294 with main.mininetLock:
295 result = main.Mininet1.addLink( self.device.name, neighbor.name )
296 if not result:
297 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
298 return EventStates().FAIL
299 with main.variableLock:
300 link.bringUp()
301 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700302 for intent in main.intents:
303 if intent.isFailed():
304 if intent.deviceA == self.device and intent.deviceB.isUp() or\
Jon Hall2bb3e212017-05-24 17:07:25 -0700305 intent.deviceB == self.device and intent.deviceA.isUp():
You Wang2b687c02016-05-13 17:01:31 -0700306 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800307 # Re-assign mastership for the device
308 with main.mininetLock:
You Wang2d32ef42017-03-03 14:09:44 -0800309 main.Mininet1.assignSwController( sw=self.device.name, ip=main.ONOSip )
You Wangdb927a52016-02-26 11:03:28 -0800310 # Re-discover hosts
311 for host in self.device.hosts:
312 correspondent = None
313 for h in main.hosts:
314 if h.isUp() and h != host:
315 correspondent = h
316 break
Jon Hall2bb3e212017-05-24 17:07:25 -0700317 if correspondent is None:
You Wangdb927a52016-02-26 11:03:28 -0800318 with main.mininetLock:
319 main.Mininet1.pingall()
320 if main.enableIPv6:
321 main.Mininet1.pingall( protocol="IPv6" )
322 else:
323 ipv4Addr = None
324 ipv6Addr = None
325 for ipAddress in correspondent.ipAddresses:
Jon Hall2bb3e212017-05-24 17:07:25 -0700326 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ) and ipv6Addr is None:
You Wangdb927a52016-02-26 11:03:28 -0800327 ipv6Addr = ipAddress
Jon Hall2bb3e212017-05-24 17:07:25 -0700328 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ) and ipv4Addr is None:
You Wangdb927a52016-02-26 11:03:28 -0800329 ipv4Addr = ipAddress
Jon Hall2bb3e212017-05-24 17:07:25 -0700330 assert ipv4Addr is not None
You Wangdb927a52016-02-26 11:03:28 -0800331 host.handle.pingHostSetAlternative( [ ipv4Addr ], 1 )
332 if main.enableIPv6:
Jon Hall2bb3e212017-05-24 17:07:25 -0700333 assert ipv6Addr is not None
You Wangdb927a52016-02-26 11:03:28 -0800334 host.handle.pingHostSetAlternative( [ ipv6Addr ], 1, True )
335 with main.variableLock:
336 host.bringUp()
337 return EventStates().PASS