blob: 7247ecf1215ae4e0687b5772f0969ba376ea43b4 [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
7from tests.CHOTestMonkey.dependencies.GraphHelper import GraphHelper
8
9class LinkEvent( Event ):
10 def __init__( self ):
11 Event.__init__( self )
12 self.linkA = None
13 self.linkB = None
14
15 def startLinkEvent( self ):
16 return EventStates().PASS
17
18 def startEvent( self, args ):
19 """
20 args are the names of the two link ends, e.g. ['s1', 's2']
21 """
22 with self.eventLock:
23 main.log.info( "%s - starting event" % ( self.typeString ) )
24 if len( args ) < 2:
25 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
26 return EventStates().ABORT
27 elif len( args ) > 2:
28 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
29 return EventStates().ABORT
30 if args[ 0 ] == 'random' or args[ 1 ] == 'random':
31 import random
32 if self.typeIndex == EventType().NETWORK_LINK_DOWN:
33 with main.variableLock:
34 graphHelper = GraphHelper()
35 availableLinks = graphHelper.getNonCutEdges()
36 if len( availableLinks ) == 0:
37 main.log.warn( "All links are cut edges, aborting event" )
38 return EventStates().ABORT
39 linkList = random.sample( availableLinks, 1 )
40 self.linkA = linkList[ 0 ]
41 self.linkB = linkList[ 0 ].backwardLink
42 elif self.typeIndex == EventType().NETWORK_LINK_UP:
43 with main.variableLock:
44 downLinks = []
45 for link in main.links:
46 if link.isDown():
47 downLinks.append( link )
48 if len( downLinks ) == 0:
49 main.log.warn( "None of the links are in 'down' state, aborting event" )
50 return EventStates().ABORT
51 linkList = random.sample( downLinks, 1 )
52 self.linkA = linkList[ 0 ]
53 self.linkB = linkList[ 0 ].backwardLink
54 elif args[ 0 ] == args[ 1 ]:
55 main.log.warn( "%s - invalid arguments: %s" % ( self.typeString, args ) )
56 return EventStates().ABORT
57 else:
58 for link in main.links:
59 if link.deviceA.name == args[ 0 ] and link.deviceB.name == args[ 1 ]:
60 self.linkA = link
61 elif link.deviceA.name == args[ 1 ] and link.deviceB.name == args[ 0 ]:
62 self.linkB = link
63 if self.linkA != None and self.linkB != None:
64 break
65 if self.linkA == None or self.linkB == None:
66 main.log.warn( "Bidirectional link %s - %s does not exist: " % ( args[ 0 ], args[ 1 ] ) )
67 return EventStates().ABORT
68 main.log.debug( "%s - %s" % ( self.typeString, self.linkA ) )
69 return self.startLinkEvent()
70
71class LinkDown( LinkEvent ):
72 """
73 Generate a link down event giving the two ends of the link
74 """
75 def __init__( self ):
76 LinkEvent.__init__( self )
77 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
78 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
79
80 def startLinkEvent( self ):
81 # TODO: do we need to handle a unidirectional link?
82 assert self.linkA != None and self.linkB != None
83 with main.variableLock:
84 if self.linkA.isDown() or self.linkB.isDown():
85 main.log.warn( "Link Down - link already down" )
86 return EventStates().ABORT
87 elif self.linkA.isRemoved() or self.linkB.isRemoved():
88 main.log.warn( "Link Down - link has been removed" )
89 return EventStates().ABORT
90 with main.mininetLock:
91 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
92 END2=self.linkA.deviceB.name,
93 OPTION="down")
94 if not result:
95 main.log.warn( "%s - failed to bring down link" % ( self.typeString ) )
96 return EventStates().FAIL
97 with main.variableLock:
98 self.linkA.bringDown()
99 self.linkB.bringDown()
100 return EventStates().PASS
101
102class LinkUp( LinkEvent ):
103 """
104 Generate a link up event giving the two ends of the link
105 """
106 def __init__( self ):
107 LinkEvent.__init__( self )
108 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
109 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
110
111 def startLinkEvent( self ):
112 assert self.linkA != None and self.linkB != None
113 with main.variableLock:
114 if self.linkA.isUp() or self.linkB.isUp():
115 main.log.warn( "Link Up - link already up" )
116 return EventStates().ABORT
117 if self.linkA.isRemoved() or self.linkB.isRemoved():
118 main.log.warn( "Link Up - link has been removed" )
119 return EventStates().ABORT
120 with main.mininetLock:
121 result = main.Mininet1.link( END1=self.linkA.deviceA.name,
122 END2=self.linkA.deviceB.name,
123 OPTION="up")
124 if not result:
125 main.log.warn( "%s - failed to bring up link" % ( self.typeString ) )
126 return EventStates().FAIL
127 with main.variableLock:
128 self.linkA.bringUp()
129 self.linkB.bringUp()
130 return EventStates().PASS
131
132class DeviceEvent( Event ):
133 def __init__( self ):
134 Event.__init__( self )
135 self.device = None
136
137 def startDeviceEvent( self ):
138 return EventStates().PASS
139
140 def startEvent( self, args ):
141 """
142 args are the names of the device, e.g. 's1'
143 """
144 with self.eventLock:
145 main.log.info( "%s - starting event" % ( self.typeString ) )
146 if len( args ) < 1:
147 main.log.warn( "%s - Not enough arguments: %s" % ( self.typeString, args ) )
148 return EventStates().ABORT
149 elif len( args ) > 1:
150 main.log.warn( "%s - Too many arguments: %s" % ( self.typeString, args ) )
151 return EventStates().ABORT
152 if args[ 0 ] == 'random':
153 import random
154 if self.typeIndex == EventType().NETWORK_DEVICE_DOWN:
155 with main.variableLock:
156 graphHelper = GraphHelper()
157 availableDevices = graphHelper.getNonCutVertices()
158 if len( availableDevices ) == 0:
159 main.log.warn( "All devices are cut vertices, aborting event" )
160 return EventStates().ABORT
161 deviceList = random.sample( availableDevices, 1 )
162 self.device = deviceList[ 0 ]
163 elif self.typeIndex == EventType().NETWORK_DEVICE_UP:
164 with main.variableLock:
165 removedDevices = []
166 for device in main.devices:
167 if device.isRemoved():
168 removedDevices.append( device )
169 if len( removedDevices ) == 0:
170 main.log.warn( "None of the devices are removed, aborting event" )
171 return EventStates().ABORT
172 deviceList = random.sample( removedDevices, 1 )
173 self.device = deviceList[ 0 ]
174 else:
175 for device in main.devices:
176 if device.name == args[ 0 ]:
177 self.device = device
178 if self.device == None:
179 main.log.warn( "Device %s does not exist: " % ( args[ 0 ] ) )
180 return EventStates().ABORT
181 main.log.debug( "%s - %s" % ( self.typeString, self.device ) )
182 return self.startDeviceEvent()
183
184class DeviceDown( DeviceEvent ):
185 """
186 Generate a device down event (which actually removes this device for now) giving its name
187 """
188 def __init__( self ):
189 DeviceEvent.__init__( self )
190 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
191 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
192
193 def startDeviceEvent( self ):
194 assert self.device != None
195 with main.variableLock:
196 if self.device.isRemoved():
197 main.log.warn( "Device Down - device has been removed" )
198 return EventStates().ABORT
199 with main.mininetLock:
200 result = main.Mininet1.delSwitch( self.device.name )
201 if not result:
202 main.log.warn( "%s - failed to bring down device" % ( self.typeString ) )
203 return EventStates().FAIL
204 with main.variableLock:
205 self.device.setRemoved()
206 for link in self.device.outgoingLinks:
207 link.setRemoved()
208 link.backwardLink.setRemoved()
209 for host in self.device.hosts:
210 host.setRemoved()
You Wang2b687c02016-05-13 17:01:31 -0700211 for intent in main.intents:
212 if intent.deviceA == self.device or intent.deviceB == self.device:
213 intent.setFailed()
You Wangdb927a52016-02-26 11:03:28 -0800214 return EventStates().PASS
215
216class DeviceUp( DeviceEvent ):
217 """
218 Generate a device up event (which re-adds this device in case the device is removed) giving its name
219 """
220 def __init__( self ):
221 DeviceEvent.__init__( self )
222 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
223 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
224
225 def startDeviceEvent( self ):
226 assert self.device != None
227 with main.variableLock:
228 if self.device.isUp():
229 main.log.warn( "Device Up - device already up" )
230 return EventStates().ABORT
231 # Re-add the device
232 with main.mininetLock:
233 result = main.Mininet1.addSwitch( self.device.name, dpid=self.device.dpid[3:] )
234 if not result:
235 main.log.warn( "%s - failed to re-add device" % ( self.typeString ) )
236 return EventStates().FAIL
237 with main.variableLock:
238 self.device.bringUp()
239 # Re-add links
240 # We add host-device links first since we did the same in mininet topology file
241 # TODO: a more rubust way is to add links according to the port info of the device
242 for host in self.device.hosts:
243 # Add host-device link
244 with main.mininetLock:
245 result = main.Mininet1.addLink( self.device.name, host.name )
246 if not result:
247 main.log.warn( "%s - failed to re-connect host %s to device" % ( self.typeString, host.name ) )
248 return EventStates().FAIL
249 for link in self.device.outgoingLinks:
250 neighbor = link.deviceB
251 # Skip bringing up any link that connecting this device to a removed neighbor
252 if neighbor.isRemoved():
253 continue
254 with main.mininetLock:
255 result = main.Mininet1.addLink( self.device.name, neighbor.name )
256 if not result:
257 main.log.warn( "%s - failed to re-add link to %s" % ( self.typeString, neighbor.name ) )
258 return EventStates().FAIL
259 with main.variableLock:
260 link.bringUp()
261 link.backwardLink.bringUp()
You Wang2b687c02016-05-13 17:01:31 -0700262 for intent in main.intents:
263 if intent.isFailed():
264 if intent.deviceA == self.device and intent.deviceB.isUp() or\
265 intent.deviceB == self.device and intent.deviceA.isUp():
266 intent.setInstalled()
You Wangdb927a52016-02-26 11:03:28 -0800267 # Re-assign mastership for the device
268 with main.mininetLock:
269 main.Mininet1.assignSwController( sw=self.device.name, ip=main.onosIPs )
270 # Re-discover hosts
271 for host in self.device.hosts:
272 correspondent = None
273 for h in main.hosts:
274 if h.isUp() and h != host:
275 correspondent = h
276 break
277 if correspondent == None:
278 with main.mininetLock:
279 main.Mininet1.pingall()
280 if main.enableIPv6:
281 main.Mininet1.pingall( protocol="IPv6" )
282 else:
283 ipv4Addr = None
284 ipv6Addr = None
285 for ipAddress in correspondent.ipAddresses:
286 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ) and ipv6Addr == None:
287 ipv6Addr = ipAddress
288 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ) and ipv4Addr == None:
289 ipv4Addr = ipAddress
290 assert ipv4Addr != None
291 host.handle.pingHostSetAlternative( [ ipv4Addr ], 1 )
292 if main.enableIPv6:
293 assert ipv6Addr != None
294 host.handle.pingHostSetAlternative( [ ipv6Addr ], 1, True )
295 with main.variableLock:
296 host.bringUp()
297 return EventStates().PASS