blob: 5632e1202cfeb5e5c55e733b24062bfd8c965ef8 [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -07002Copyright 2016 Open Networking Foundation ( ONF )
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -07003
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
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070011 ( at your option ) any later version.
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070012
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"""
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070021"""
You Wangdb927a52016-02-26 11:03:28 -080022This file contains classes for CHOTestMonkey that are related to network event
23Author: you@onlab.us
24"""
25from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
26from tests.CHOTestMonkey.dependencies.elements.NetworkElement import NetworkElement, Device, Host, Link
You Wangdb927a52016-02-26 11:03:28 -080027
Jon Hall2bb3e212017-05-24 17:07:25 -070028
You Wangdb927a52016-02-26 11:03:28 -080029class LinkEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -070030
You Wangdb927a52016-02-26 11:03:28 -080031 def __init__( self ):
32 Event.__init__( self )
33 self.linkA = None
34 self.linkB = None
35
36 def startLinkEvent( self ):
37 return EventStates().PASS
38
39 def startEvent( self, args ):
40 """
Jon Hall2bb3e212017-05-24 17:07:25 -070041 args are the names of the two link ends, e.g. [ 's1', 's2' ]
You Wangdb927a52016-02-26 11:03:28 -080042 """
43 with self.eventLock:
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070044 # main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080045 if len( args ) < 2:
46 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
47 return EventStates().ABORT
48 elif len( args ) > 2:
49 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
50 return EventStates().ABORT
51 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
You Wangdb927a52016-02-26 11:03:28 -080052 if self.typeIndex == EventType().NETWORK_LINK_DOWN:
You Wang221db322016-06-03 15:45:52 -070053 with main.mininetLock:
54 linkRandom = main.Mininet1.getLinkRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -070055 if linkRandom is None:
You Wang221db322016-06-03 15:45:52 -070056 main.log.warn( "No link available, aborting event" )
57 return EventStates().ABORT
58 args[ 0 ] = linkRandom[ 0 ]
59 args[ 1 ] = linkRandom[ 1 ]
You Wangdb927a52016-02-26 11:03:28 -080060 elif self.typeIndex == EventType().NETWORK_LINK_UP:
You Wang221db322016-06-03 15:45:52 -070061 import random
You Wangdb927a52016-02-26 11:03:28 -080062 with main.variableLock:
63 downLinks = []
64 for link in main.links:
65 if link.isDown():
66 downLinks.append( link )
67 if len( downLinks ) == 0:
68 main.log.warn( "None of the links are in 'down' state, aborting event" )
69 return EventStates().ABORT
70 linkList = random.sample( downLinks, 1 )
71 self.linkA = linkList[ 0 ]
72 self.linkB = linkList[ 0 ].backwardLink
73 elif args[ 0 ] == args[ 1 ]:
74 main.log.warn( "%s - invalid arguments: %s" % ( self.typeString, args ) )
75 return EventStates().ABORT
Jon Hall2bb3e212017-05-24 17:07:25 -070076 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080077 for link in main.links:
78 if link.deviceA.name == args[ 0 ] and link.deviceB.name == args[ 1 ]:
79 self.linkA = link
80 elif link.deviceA.name == args[ 1 ] and link.deviceB.name == args[ 0 ]:
81 self.linkB = link
Jon Hall2bb3e212017-05-24 17:07:25 -070082 if self.linkA is not None and self.linkB is not None:
You Wangdb927a52016-02-26 11:03:28 -080083 break
Jon Hall2bb3e212017-05-24 17:07:25 -070084 if self.linkA is None or self.linkB is None:
You Wangdb927a52016-02-26 11:03:28 -080085 main.log.warn( "Bidirectional link %s - %s does not exist: " % ( args[ 0 ], args[ 1 ] ) )
86 return EventStates().ABORT
87 main.log.debug( "%s - %s" % ( self.typeString, self.linkA ) )
88 return self.startLinkEvent()
89
Jon Hall2bb3e212017-05-24 17:07:25 -070090
You Wangdb927a52016-02-26 11:03:28 -080091class LinkDown( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070092
You Wangdb927a52016-02-26 11:03:28 -080093 """
94 Generate a link down event giving the two ends of the link
95 """
96 def __init__( self ):
97 LinkEvent.__init__( self )
98 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
99 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
100
101 def startLinkEvent( self ):
102 # TODO: do we need to handle a unidirectional link?
Jon Hall2bb3e212017-05-24 17:07:25 -0700103 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -0800104 with main.variableLock:
105 if self.linkA.isDown() or self.linkB.isDown():
106 main.log.warn( "Link Down - link already down" )
107 return EventStates().ABORT
108 elif self.linkA.isRemoved() or self.linkB.isRemoved():
109 main.log.warn( "Link Down - link has been removed" )
110 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700111 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 -0800112 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700113 """
You Wangdb927a52016-02-26 11:03:28 -0800114 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
115 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -0700116 OPTION="down" )
117 """
You Wang221db322016-06-03 15:45:52 -0700118 result = main.Mininet1.delLink( self.linkA.deviceA.name,
119 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800120 if not result:
121 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
122 return EventStates().FAIL
123 with main.variableLock:
124 self.linkA.bringDown()
125 self.linkB.bringDown()
126 return EventStates().PASS
127
Jon Hall2bb3e212017-05-24 17:07:25 -0700128
You Wangdb927a52016-02-26 11:03:28 -0800129class LinkUp( LinkEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700130
You Wangdb927a52016-02-26 11:03:28 -0800131 """
132 Generate a link up event giving the two ends of the link
133 """
134 def __init__( self ):
135 LinkEvent.__init__( self )
136 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
137 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
138
139 def startLinkEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700140 assert self.linkA is not None and self.linkB is not None
You Wangdb927a52016-02-26 11:03:28 -0800141 with main.variableLock:
142 if self.linkA.isUp() or self.linkB.isUp():
143 main.log.warn( "Link Up - link already up" )
144 return EventStates().ABORT
145 if self.linkA.isRemoved() or self.linkB.isRemoved():
146 main.log.warn( "Link Up - link has been removed" )
147 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700148 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 -0800149 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700150 """
You Wangdb927a52016-02-26 11:03:28 -0800151 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
152 END2=self.linkA.deviceB.name,
Jon Hall2bb3e212017-05-24 17:07:25 -0700153 OPTION="up" )
154 """
You Wang221db322016-06-03 15:45:52 -0700155 result = main.Mininet1.addLink( self.linkA.deviceA.name,
156 self.linkA.deviceB.name )
You Wangdb927a52016-02-26 11:03:28 -0800157 if not result:
158 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
159 return EventStates().FAIL
160 with main.variableLock:
161 self.linkA.bringUp()
162 self.linkB.bringUp()
163 return EventStates().PASS
164
Jon Hall2bb3e212017-05-24 17:07:25 -0700165
You Wangdb927a52016-02-26 11:03:28 -0800166class DeviceEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700167
You Wangdb927a52016-02-26 11:03:28 -0800168 def __init__( self ):
169 Event.__init__( self )
170 self.device = None
171
172 def startDeviceEvent( self ):
173 return EventStates().PASS
174
175 def startEvent( self, args ):
176 """
177 args are the names of the device, e.g. 's1'
178 """
179 with self.eventLock:
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700180 # main.log.info( "%s - starting event" % ( self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -0800181 if len( args ) < 1:
182 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
183 return EventStates().ABORT
184 elif len( args ) > 1:
185 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
186 return EventStates().ABORT
187 if args[ 0 ] == 'random':
188 import random
189 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
You Wang221db322016-06-03 15:45:52 -0700190 with main.mininetLock:
191 switchRandom = main.Mininet1.getSwitchRandom()
Jon Hall2bb3e212017-05-24 17:07:25 -0700192 if switchRandom is None:
You Wang221db322016-06-03 15:45:52 -0700193 main.log.warn( "No switch available, aborting event" )
194 return EventStates().ABORT
195 args[ 0 ] = switchRandom
You Wangdb927a52016-02-26 11:03:28 -0800196 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
197 with main.variableLock:
198 removedDevices = []
199 for device in main.devices:
200 if device.isRemoved():
201 removedDevices.append( device )
202 if len( removedDevices ) == 0:
203 main.log.warn( "None of the devices are removed, aborting event" )
204 return EventStates().ABORT
205 deviceList = random.sample( removedDevices, 1 )
206 self.device = deviceList[ 0 ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700207 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800208 for device in main.devices:
209 if device.name == args[ 0 ]:
210 self.device = device
Jon Hall2bb3e212017-05-24 17:07:25 -0700211 if self.device is None:
You Wangdb927a52016-02-26 11:03:28 -0800212 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
213 return EventStates().ABORT
214 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
215 return self.startDeviceEvent()
216
Jon Hall2bb3e212017-05-24 17:07:25 -0700217
You Wangdb927a52016-02-26 11:03:28 -0800218class DeviceDown( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700219
You Wangdb927a52016-02-26 11:03:28 -0800220 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700221 Generate a device down event ( which actually removes this device for now ) giving its name
You Wangdb927a52016-02-26 11:03:28 -0800222 """
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 ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700229 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800230 with main.variableLock:
231 if self.device.isRemoved():
232 main.log.warn( "Device Down - device has been removed" )
233 return EventStates().ABORT
You Wang52163202016-07-14 16:37:15 -0700234 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800235 with main.mininetLock:
236 result = main.Mininet1.delSwitch( self.device.name )
237 if not result:
238 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
239 return EventStates().FAIL
240 with main.variableLock:
241 self.device.setRemoved()
242 for link in self.device.outgoingLinks:
243 link.setRemoved()
244 link.backwardLink.setRemoved()
245 for host in self.device.hosts:
246 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700247 for intent in main.intents:
248 if intent.deviceA == self.device or intent.deviceB == self.device:
249 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800250 return EventStates().PASS
251
Jon Hall2bb3e212017-05-24 17:07:25 -0700252
You Wangdb927a52016-02-26 11:03:28 -0800253class DeviceUp( DeviceEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700254
You Wangdb927a52016-02-26 11:03:28 -0800255 """
Jon Hall2bb3e212017-05-24 17:07:25 -0700256 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 -0800257 """
258 def __init__( self ):
259 DeviceEvent.__init__( self )
260 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
261 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
262
263 def startDeviceEvent( self ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700264 assert self.device is not None
You Wangdb927a52016-02-26 11:03:28 -0800265 with main.variableLock:
266 if self.device.isUp():
267 main.log.warn( "Device Up - device already up" )
268 return EventStates().ABORT
269 # Re-add the device
You Wang52163202016-07-14 16:37:15 -0700270 main.log.info( "Event recorded: {} {} {}".format( self.typeIndex, self.typeString, self.device.name ) )
You Wangdb927a52016-02-26 11:03:28 -0800271 with main.mininetLock:
Jon Hall2bb3e212017-05-24 17:07:25 -0700272 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[ 3: ] )
You Wangdb927a52016-02-26 11:03:28 -0800273 if not result:
274 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
275 return EventStates().FAIL
276 with main.variableLock:
277 self.device.bringUp()
278 # Re-add links
279 # We add host-device links first since we did the same in mininet topology file
280 # TODO: a more rubust way is to add links according to the port info of the device
281 for host in self.device.hosts:
282 # Add host-device link
283 with main.mininetLock:
284 result = main.Mininet1.addLink( self.device.name, host.name )
285 if not result:
286 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
287 return EventStates().FAIL
288 for link in self.device.outgoingLinks:
289 neighbor = link.deviceB
290 # Skip bringing up any link that connecting this device to a removed neighbor
291 if neighbor.isRemoved():
292 continue
293 with main.mininetLock:
294 result = main.Mininet1.addLink( self.device.name, neighbor.name )
295 if not result:
296 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
297 return EventStates().FAIL
298 with main.variableLock:
299 link.bringUp()
300 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700301 for intent in main.intents:
302 if intent.isFailed():
303 if intent.deviceA == self.device and intent.deviceB.isUp() or\
Jon Hall2bb3e212017-05-24 17:07:25 -0700304 intent.deviceB == self.device and intent.deviceA.isUp():
You Wang2b687c02016-05-13 17:01:31 -0700305 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800306 # Re-assign mastership for the device
307 with main.mininetLock:
Devin Lim142b5342017-07-20 15:22:39 -0700308 ips = main.Cluster.getIps()
309 main.Mininet1.assignSwController( sw=self.device.name, ip=ips )
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