blob: 579b17f66f9fb2a8dce4f305f0bd494c001e0a2f [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 check event
23Author: you@onlab.us
24"""
25from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
26
Jon Hall2bb3e212017-05-24 17:07:25 -070027
You Wangdb927a52016-02-26 11:03:28 -080028class CheckEvent( Event ):
Jon Hall2bb3e212017-05-24 17:07:25 -070029
You Wangdb927a52016-02-26 11:03:28 -080030 def __init__( self ):
31 Event.__init__( self )
32
33 def startCheckEvent( self ):
34 return EventStates().PASS
35
36 def startEvent( self, args ):
37 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070038 main.log.info( "Event recorded: {} {}".format( self.typeIndex, self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080039 result = self.startCheckEvent()
40 return result
41
Jon Hall2bb3e212017-05-24 17:07:25 -070042
You Wangdb927a52016-02-26 11:03:28 -080043class IntentCheck( CheckEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070044
You Wangdb927a52016-02-26 11:03:28 -080045 def __init__( self ):
46 CheckEvent.__init__( self )
47 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
48 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
49
50 def startCheckEvent( self, args=None ):
51 checkResult = EventStates().PASS
You Wang58aa11e2016-05-17 10:35:44 -070052 intentDict = {}
You Wangdb927a52016-02-26 11:03:28 -080053 for intent in main.intents:
You Wang58aa11e2016-05-17 10:35:44 -070054 intentDict[ intent.id ] = intent.expectedState
You Wangdb927a52016-02-26 11:03:28 -080055 for controller in main.controllers:
56 if controller.isUp():
57 with controller.CLILock:
You Wang58aa11e2016-05-17 10:35:44 -070058 intentState = controller.CLI.compareIntent( intentDict )
You Wangdb927a52016-02-26 11:03:28 -080059 if not intentState:
You Wang58aa11e2016-05-17 10:35:44 -070060 main.log.warn( "Intent Check - not all intent ids and states match that on ONOS%s" % ( controller.index ) )
You Wangdb927a52016-02-26 11:03:28 -080061 checkResult = EventStates().FAIL
You Wang58aa11e2016-05-17 10:35:44 -070062 return checkResult
63
Jon Hall2bb3e212017-05-24 17:07:25 -070064
You Wang58aa11e2016-05-17 10:35:44 -070065class FlowCheck( CheckEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -070066
You Wang58aa11e2016-05-17 10:35:44 -070067 def __init__( self ):
68 CheckEvent.__init__( self )
69 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
70 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
71
72 def startCheckEvent( self, args=None ):
73 import json
74 checkResult = EventStates().PASS
You Wang3c276252016-09-21 15:21:36 -070075 if main.enableIPv6:
You Wang62e1cf62016-09-22 17:13:03 -070076 coreFlowNum = int( main.params[ 'EVENT' ][ 'FlowCheck' ][ 'coreFlowNum6' ] )
You Wang3c276252016-09-21 15:21:36 -070077 else:
You Wang62e1cf62016-09-22 17:13:03 -070078 coreFlowNum = int( main.params[ 'EVENT' ][ 'FlowCheck' ][ 'coreFlowNum' ] )
You Wang58aa11e2016-05-17 10:35:44 -070079 for controller in main.controllers:
80 if controller.isUp():
81 with controller.CLILock:
You Wang3c276252016-09-21 15:21:36 -070082 # Check core flow number
83 for device in main.devices:
84 if device.isRemoved():
85 continue
86 coreFlowNumOnos = controller.CLI.flowAddedCount( device.dpid, core=True )
Jon Hall2bb3e212017-05-24 17:07:25 -070087 if coreFlowNumOnos is None:
You Wang3c276252016-09-21 15:21:36 -070088 main.log.warn( "Flow Check - error when trying to get flow number of %s on ONOS%s" % ( device.dpid, controller.index ) )
89 checkResult = EventStates().FAIL
90 else:
91 coreFlowNumOnos = int( coreFlowNumOnos )
92 if coreFlowNumOnos != coreFlowNum:
93 main.log.warn( "Flow Check - core flow number of %s on ONOS%s is %s" % ( device.dpid, controller.index, coreFlowNumOnos ) )
94 checkResult = EventStates().FAIL
95 # Get flows for comparison
You Wang58aa11e2016-05-17 10:35:44 -070096 flows = controller.CLI.flows()
97 try:
98 flows = json.loads( flows )
99 except ( TypeError, ValueError ):
100 main.log.exception( "Flow Check - Object not as expected: {!r}".format( flows ) )
101 return EventStates().FAIL
102 # Compare flow IDs in ONOS and Mininet
103 flowIDList = []
104 for item in flows:
105 for flow in item[ "flows" ]:
106 flowIDList.append( hex( int( flow[ 'id' ] ) ) )
107 main.log.info( "Flow Check - current flow number on ONOS%s: %s" % ( controller.index, len( flowIDList ) ) )
108 switchList = []
109 for device in main.devices:
110 switchList.append( device.name )
111 with main.mininetLock:
112 flowCompareResult = main.Mininet1.checkFlowId( switchList, flowIDList, debug=False )
113 if not flowCompareResult:
114 main.log.warn( "Flow Check - flows on ONOS%s do not match that in Mininet" % ( controller.index ) )
115 checkResult = EventStates().FAIL
116 # Check flow state
117 flowState = controller.CLI.checkFlowsState( isPENDING=False )
118 if not flowState:
119 main.log.warn( "Flow Check - not all flows are in ADDED state on ONOS%s" % ( controller.index ) )
120 checkResult = EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -0800121 return checkResult
122
Jon Hall2bb3e212017-05-24 17:07:25 -0700123
You Wangdb927a52016-02-26 11:03:28 -0800124class TopoCheck( CheckEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700125
You Wangdb927a52016-02-26 11:03:28 -0800126 def __init__( self ):
127 CheckEvent.__init__( self )
128 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
129 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
130
131 def startCheckEvent( self, args=None ):
132 import json
133 checkResult = EventStates().PASS
134 upLinkNum = 0
135 upDeviceNum = 0
136 upHostNum = 0
137 with main.variableLock:
138 for link in main.links:
139 if not link.isDown() and not link.isRemoved():
140 upLinkNum += 1
141 for device in main.devices:
142 if not device.isDown() and not device.isRemoved():
143 upDeviceNum += 1
144 for host in main.hosts:
145 if not host.isDown() and not host.isRemoved():
146 upHostNum += 1
147 clusterNum = 1
You Wang221db322016-06-03 15:45:52 -0700148 with main.mininetLock:
149 graphDictMininet = main.Mininet1.getGraphDict( useId=True )
You Wangdb927a52016-02-26 11:03:28 -0800150 for controller in main.controllers:
151 if controller.isUp():
152 with controller.CLILock:
Flavio Castro82ee2f62016-06-07 15:04:12 -0700153 topoState = controller.CLI.checkStatus( upDeviceNum, upLinkNum )
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700154 # if not topoState:
You Wangdb927a52016-02-26 11:03:28 -0800155 # main.log.warn( "Topo Check - link or device number discoverd by ONOS%s is incorrect" % ( controller.index ) )
156 # checkResult = EventStates().FAIL
You Wang221db322016-06-03 15:45:52 -0700157 # Compare ONOS and Mininet topologies
158 graphDictONOS = controller.CLI.getGraphDict()
159 compareResult = main.graph.compareGraphs( graphDictONOS, graphDictMininet )
160 if not compareResult:
161 checkResult = EventStates().FAIL
162 main.log.warn( "Topo Check - ONOS and Mininet topologies do not match" )
You Wang58aa11e2016-05-17 10:35:44 -0700163 try:
You Wang221db322016-06-03 15:45:52 -0700164 # Check links
You Wang58aa11e2016-05-17 10:35:44 -0700165 links = controller.CLI.links()
166 links = json.loads( links )
167 if not len( links ) == upLinkNum:
168 checkResult = EventStates().FAIL
169 main.log.warn( "Topo Check - link number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upLinkNum, len( links ) ) )
170 # Check devices
171 devices = controller.CLI.devices()
172 devices = json.loads( devices )
173 availableDeviceNum = 0
174 for device in devices:
Jon Hall2bb3e212017-05-24 17:07:25 -0700175 if device[ 'available' ]:
You Wang58aa11e2016-05-17 10:35:44 -0700176 availableDeviceNum += 1
177 if not availableDeviceNum == upDeviceNum:
178 checkResult = EventStates().FAIL
179 main.log.warn( "Topo Check - device number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upDeviceNum, availableDeviceNum ) )
180 # Check hosts
181 hosts = controller.CLI.hosts()
182 hosts = json.loads( hosts )
183 if not len( hosts ) == upHostNum:
184 checkResult = EventStates().FAIL
185 main.log.warn( "Topo Check - host number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upHostNum, len( hosts ) ) )
186 # Check clusters
187 clusters = controller.CLI.clusters()
188 clusters = json.loads( clusters )
189 if not len( clusters ) == clusterNum:
190 checkResult = EventStates().FAIL
191 main.log.warn( "Topo Check - cluster number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, clusterNum, len( clusters ) ) )
192 except ( TypeError, ValueError ):
193 main.log.exception( "Flow Check - Object not as expected" )
194 return EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -0800195 return checkResult
196
Jon Hall2bb3e212017-05-24 17:07:25 -0700197
You Wangdb927a52016-02-26 11:03:28 -0800198class ONOSCheck( CheckEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700199
You Wangdb927a52016-02-26 11:03:28 -0800200 def __init__( self ):
201 CheckEvent.__init__( self )
202 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700203 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800204
205 def startCheckEvent( self, args=None ):
206 import json
207 checkResult = EventStates().PASS
208 topics = []
209 # TODO: Other topics?
210 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700211 topics.append( "work-partition-" + str( i ) )
You Wangdb927a52016-02-26 11:03:28 -0800212 dpidToAvailability = {}
213 dpidToMaster = {}
214 for device in main.devices:
215 if device.isDown() or device.isRemoved():
216 dpidToAvailability[ device.dpid ] = False
217 else:
218 dpidToAvailability[ device.dpid ] = True
219 dpidToMaster[ device.dpid ] = 'unknown'
220 # Check mastership, leaders and node states on each controller node
221 for controller in main.controllers:
222 if controller.isUp():
223 # Check mastership
You Wang58aa11e2016-05-17 10:35:44 -0700224 try:
225 with controller.CLILock:
226 roles = controller.CLI.roles()
227 roles = json.loads( roles )
228 for device in roles:
229 dpid = device[ 'id' ]
230 if dpidToMaster[ dpid ] == 'unknown':
231 dpidToMaster[ dpid ] = device[ 'master' ]
232 elif dpidToMaster[ dpid ] != device[ 'master' ]:
233 checkResult = EventStates().FAIL
234 main.log.warn( "ONOS Check - Mastership of %s on ONOS%s is inconsistent with that on ONOS1" % ( dpid, controller.index ) )
235 if dpidToAvailability[ dpid ] and device[ 'master' ] == "none":
236 checkResult = EventStates().FAIL
237 main.log.warn( "ONOS Check - Device %s has no master on ONOS%s" % ( dpid, controller.index ) )
238 # Check leaders
239 with controller.CLILock:
240 leaders = controller.CLI.leaders()
241 leaders = json.loads( leaders )
Jon Hall2bb3e212017-05-24 17:07:25 -0700242 ONOSTopics = [ j[ 'topic' ] for j in leaders ]
You Wang58aa11e2016-05-17 10:35:44 -0700243 for topic in topics:
244 if topic not in ONOSTopics:
245 checkResult = EventStates().FAIL
246 main.log.warn( "ONOS Check - Topic %s not in leaders on ONOS%s" % ( topic, controller.index ) )
247 # Check node state
248 with controller.CLILock:
249 nodes = controller.CLI.nodes()
250 nodes = json.loads( nodes )
251 ipToState = {}
252 for node in nodes:
253 ipToState[ node[ 'ip' ] ] = node[ 'state' ]
254 for c in main.controllers:
255 if c.isUp() and ipToState[ c.ip ] == 'READY':
256 pass
257 elif not c.isUp() and ipToState[ c.ip ] == 'INACTIVE':
258 pass
259 else:
260 checkResult = EventStates().FAIL
261 main.log.warn( "ONOS Check - ONOS%s shows wrong node state: ONOS%s is %s but state is %s" % ( controller.index, c.index, c.status, ipToState[ c.ip ] ) )
262 # TODO: check partitions?
263 except ( TypeError, ValueError ):
264 main.log.exception( "ONOS Check - Object not as expected" )
265 return EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -0800266 return checkResult
267
Jon Hall2bb3e212017-05-24 17:07:25 -0700268
You Wangdb927a52016-02-26 11:03:28 -0800269class TrafficCheck( CheckEvent ):
Jon Hall2bb3e212017-05-24 17:07:25 -0700270
You Wangdb927a52016-02-26 11:03:28 -0800271 def __init__( self ):
272 CheckEvent.__init__( self )
273 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
Jon Hall2bb3e212017-05-24 17:07:25 -0700274 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
You Wangdb927a52016-02-26 11:03:28 -0800275
276 def startCheckEvent( self, args=None ):
277 checkResult = EventStates().PASS
278 pool = []
279 wait = int( main.params[ 'EVENT' ][ 'TrafficCheck' ][ 'pingWait' ] )
280 timeout = int( main.params[ 'EVENT' ][ 'TrafficCheck' ][ 'pingTimeout' ] )
281 dstIPv4List = {}
282 dstIPv6List = {}
283 upHosts = []
284 for host in main.hosts:
285 if host.isUp():
286 upHosts.append( host )
287 for host in upHosts:
288 dstIPv4List[ host.index ] = []
289 dstIPv6List[ host.index ] = []
290 for correspondent in host.correspondents:
Jon Hall2bb3e212017-05-24 17:07:25 -0700291 if correspondent not in upHosts:
You Wangdb927a52016-02-26 11:03:28 -0800292 continue
293 for ipAddress in correspondent.ipAddresses:
294 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ):
295 dstIPv6List[ host.index ].append( ipAddress )
296 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ):
297 dstIPv4List[ host.index ].append( ipAddress )
298 thread = main.Thread( target=host.handle.pingHostSetAlternative,
299 threadID=main.threadID,
300 name="pingHostSetAlternative",
301 args=[ dstIPv4List[ host.index ], 1 ] )
302 pool.append( thread )
303 thread.start()
304 with main.variableLock:
305 main.threadID += 1
306 for thread in pool:
307 thread.join( 10 )
308 if not thread.result:
309 checkResult = EventStates().FAIL
310 main.log.warn( "Traffic Check - ping failed" )
311
312 if not main.enableIPv6:
313 return checkResult
314 # Check ipv6 ping
315 for host in upHosts:
316 thread = main.Thread( target=host.handle.pingHostSetAlternative,
317 threadID=main.threadID,
318 name="pingHostSetAlternative",
319 args=[ dstIPv6List[ host.index ], 1, True ] )
320 pool.append( thread )
321 thread.start()
322 with main.variableLock:
323 main.threadID += 1
324 for thread in pool:
325 thread.join( 10 )
326 if not thread.result:
327 checkResult = EventStates().FAIL
328 main.log.warn( "Traffic Check - ping6 failed" )
329 return checkResult
Devin Limf0822182017-09-12 14:52:57 -0700330
331class RaftLogSizeCheck( CheckEvent ):
332
333 def __init__( self ):
334 CheckEvent.__init__( self )
335 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
336 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
337
338 def startCheckEvent( self, args=None ):
339 checkResult = EventStates().PASS
340 main.log.info( "Starting checking Raft Log size" )
341 if not main.Cluster.checkPartitionSize():
342 checkResult = EventStates().FAIL
343 main.log.warn( "Raft Log Size Check - Raft log grew too big" )
344
345 return checkResult