blob: 8c85ff844e808488f316868ea068aad1fa3425dc [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
2This file contains classes for CHOTestMonkey that are related to check event
3Author: you@onlab.us
4"""
5from tests.CHOTestMonkey.dependencies.events.Event import EventType, EventStates, Event
6
7class CheckEvent( Event ):
8 def __init__( self ):
9 Event.__init__( self )
10
11 def startCheckEvent( self ):
12 return EventStates().PASS
13
14 def startEvent( self, args ):
15 with self.eventLock:
You Wang52163202016-07-14 16:37:15 -070016 main.log.info( "Event recorded: {} {}".format( self.typeIndex, self.typeString ) )
You Wangdb927a52016-02-26 11:03:28 -080017 result = self.startCheckEvent()
18 return result
19
20class IntentCheck( CheckEvent ):
21 def __init__( self ):
22 CheckEvent.__init__( self )
23 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
24 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
25
26 def startCheckEvent( self, args=None ):
27 checkResult = EventStates().PASS
You Wang58aa11e2016-05-17 10:35:44 -070028 intentDict = {}
You Wangdb927a52016-02-26 11:03:28 -080029 for intent in main.intents:
You Wang58aa11e2016-05-17 10:35:44 -070030 intentDict[ intent.id ] = intent.expectedState
You Wangdb927a52016-02-26 11:03:28 -080031 for controller in main.controllers:
32 if controller.isUp():
33 with controller.CLILock:
You Wang58aa11e2016-05-17 10:35:44 -070034 intentState = controller.CLI.compareIntent( intentDict )
You Wangdb927a52016-02-26 11:03:28 -080035 if not intentState:
You Wang58aa11e2016-05-17 10:35:44 -070036 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 -080037 checkResult = EventStates().FAIL
You Wang58aa11e2016-05-17 10:35:44 -070038 return checkResult
39
40class FlowCheck( CheckEvent ):
41 def __init__( self ):
42 CheckEvent.__init__( self )
43 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
44 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
45
46 def startCheckEvent( self, args=None ):
47 import json
48 checkResult = EventStates().PASS
You Wang3c276252016-09-21 15:21:36 -070049 if main.enableIPv6:
You Wang62e1cf62016-09-22 17:13:03 -070050 coreFlowNum = int( main.params[ 'EVENT' ][ 'FlowCheck' ][ 'coreFlowNum6' ] )
You Wang3c276252016-09-21 15:21:36 -070051 else:
You Wang62e1cf62016-09-22 17:13:03 -070052 coreFlowNum = int( main.params[ 'EVENT' ][ 'FlowCheck' ][ 'coreFlowNum' ] )
You Wang58aa11e2016-05-17 10:35:44 -070053 for controller in main.controllers:
54 if controller.isUp():
55 with controller.CLILock:
You Wang3c276252016-09-21 15:21:36 -070056 # Check core flow number
57 for device in main.devices:
58 if device.isRemoved():
59 continue
60 coreFlowNumOnos = controller.CLI.flowAddedCount( device.dpid, core=True )
61 if coreFlowNumOnos == None:
62 main.log.warn( "Flow Check - error when trying to get flow number of %s on ONOS%s" % ( device.dpid, controller.index ) )
63 checkResult = EventStates().FAIL
64 else:
65 coreFlowNumOnos = int( coreFlowNumOnos )
66 if coreFlowNumOnos != coreFlowNum:
67 main.log.warn( "Flow Check - core flow number of %s on ONOS%s is %s" % ( device.dpid, controller.index, coreFlowNumOnos ) )
68 checkResult = EventStates().FAIL
69 # Get flows for comparison
You Wang58aa11e2016-05-17 10:35:44 -070070 flows = controller.CLI.flows()
71 try:
72 flows = json.loads( flows )
73 except ( TypeError, ValueError ):
74 main.log.exception( "Flow Check - Object not as expected: {!r}".format( flows ) )
75 return EventStates().FAIL
76 # Compare flow IDs in ONOS and Mininet
77 flowIDList = []
78 for item in flows:
79 for flow in item[ "flows" ]:
80 flowIDList.append( hex( int( flow[ 'id' ] ) ) )
81 main.log.info( "Flow Check - current flow number on ONOS%s: %s" % ( controller.index, len( flowIDList ) ) )
82 switchList = []
83 for device in main.devices:
84 switchList.append( device.name )
85 with main.mininetLock:
86 flowCompareResult = main.Mininet1.checkFlowId( switchList, flowIDList, debug=False )
87 if not flowCompareResult:
88 main.log.warn( "Flow Check - flows on ONOS%s do not match that in Mininet" % ( controller.index ) )
89 checkResult = EventStates().FAIL
90 # Check flow state
91 flowState = controller.CLI.checkFlowsState( isPENDING=False )
92 if not flowState:
93 main.log.warn( "Flow Check - not all flows are in ADDED state on ONOS%s" % ( controller.index ) )
94 checkResult = EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -080095 return checkResult
96
97class TopoCheck( CheckEvent ):
98 def __init__( self ):
99 CheckEvent.__init__( self )
100 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
101 self.typeIndex = int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
102
103 def startCheckEvent( self, args=None ):
104 import json
105 checkResult = EventStates().PASS
106 upLinkNum = 0
107 upDeviceNum = 0
108 upHostNum = 0
109 with main.variableLock:
110 for link in main.links:
111 if not link.isDown() and not link.isRemoved():
112 upLinkNum += 1
113 for device in main.devices:
114 if not device.isDown() and not device.isRemoved():
115 upDeviceNum += 1
116 for host in main.hosts:
117 if not host.isDown() and not host.isRemoved():
118 upHostNum += 1
119 clusterNum = 1
You Wang221db322016-06-03 15:45:52 -0700120 with main.mininetLock:
121 graphDictMininet = main.Mininet1.getGraphDict( useId=True )
You Wangdb927a52016-02-26 11:03:28 -0800122 for controller in main.controllers:
123 if controller.isUp():
124 with controller.CLILock:
Flavio Castro82ee2f62016-06-07 15:04:12 -0700125 topoState = controller.CLI.checkStatus( upDeviceNum, upLinkNum )
You Wangdb927a52016-02-26 11:03:28 -0800126 #if not topoState:
127 # main.log.warn( "Topo Check - link or device number discoverd by ONOS%s is incorrect" % ( controller.index ) )
128 # checkResult = EventStates().FAIL
You Wang221db322016-06-03 15:45:52 -0700129 # Compare ONOS and Mininet topologies
130 graphDictONOS = controller.CLI.getGraphDict()
131 compareResult = main.graph.compareGraphs( graphDictONOS, graphDictMininet )
132 if not compareResult:
133 checkResult = EventStates().FAIL
134 main.log.warn( "Topo Check - ONOS and Mininet topologies do not match" )
You Wang58aa11e2016-05-17 10:35:44 -0700135 try:
You Wang221db322016-06-03 15:45:52 -0700136 # Check links
You Wang58aa11e2016-05-17 10:35:44 -0700137 links = controller.CLI.links()
138 links = json.loads( links )
139 if not len( links ) == upLinkNum:
140 checkResult = EventStates().FAIL
141 main.log.warn( "Topo Check - link number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upLinkNum, len( links ) ) )
142 # Check devices
143 devices = controller.CLI.devices()
144 devices = json.loads( devices )
145 availableDeviceNum = 0
146 for device in devices:
147 if device[ 'available' ] == True:
148 availableDeviceNum += 1
149 if not availableDeviceNum == upDeviceNum:
150 checkResult = EventStates().FAIL
151 main.log.warn( "Topo Check - device number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upDeviceNum, availableDeviceNum ) )
152 # Check hosts
153 hosts = controller.CLI.hosts()
154 hosts = json.loads( hosts )
155 if not len( hosts ) == upHostNum:
156 checkResult = EventStates().FAIL
157 main.log.warn( "Topo Check - host number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, upHostNum, len( hosts ) ) )
158 # Check clusters
159 clusters = controller.CLI.clusters()
160 clusters = json.loads( clusters )
161 if not len( clusters ) == clusterNum:
162 checkResult = EventStates().FAIL
163 main.log.warn( "Topo Check - cluster number discoverd by ONOS%s is incorrect: %s expected and %s actual" % ( controller.index, clusterNum, len( clusters ) ) )
164 except ( TypeError, ValueError ):
165 main.log.exception( "Flow Check - Object not as expected" )
166 return EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -0800167 return checkResult
168
169class ONOSCheck( CheckEvent ):
170 def __init__( self ):
171 CheckEvent.__init__( self )
172 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
173 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
174
175 def startCheckEvent( self, args=None ):
176 import json
177 checkResult = EventStates().PASS
178 topics = []
179 # TODO: Other topics?
180 for i in range( 14 ):
Jon Hall8dafdcc2016-09-16 10:21:25 -0700181 topics.append( "work-partition-" + str( i ) )
You Wangdb927a52016-02-26 11:03:28 -0800182 dpidToAvailability = {}
183 dpidToMaster = {}
184 for device in main.devices:
185 if device.isDown() or device.isRemoved():
186 dpidToAvailability[ device.dpid ] = False
187 else:
188 dpidToAvailability[ device.dpid ] = True
189 dpidToMaster[ device.dpid ] = 'unknown'
190 # Check mastership, leaders and node states on each controller node
191 for controller in main.controllers:
192 if controller.isUp():
193 # Check mastership
You Wang58aa11e2016-05-17 10:35:44 -0700194 try:
195 with controller.CLILock:
196 roles = controller.CLI.roles()
197 roles = json.loads( roles )
198 for device in roles:
199 dpid = device[ 'id' ]
200 if dpidToMaster[ dpid ] == 'unknown':
201 dpidToMaster[ dpid ] = device[ 'master' ]
202 elif dpidToMaster[ dpid ] != device[ 'master' ]:
203 checkResult = EventStates().FAIL
204 main.log.warn( "ONOS Check - Mastership of %s on ONOS%s is inconsistent with that on ONOS1" % ( dpid, controller.index ) )
205 if dpidToAvailability[ dpid ] and device[ 'master' ] == "none":
206 checkResult = EventStates().FAIL
207 main.log.warn( "ONOS Check - Device %s has no master on ONOS%s" % ( dpid, controller.index ) )
208 # Check leaders
209 with controller.CLILock:
210 leaders = controller.CLI.leaders()
211 leaders = json.loads( leaders )
212 ONOSTopics = [ j['topic'] for j in leaders ]
213 for topic in topics:
214 if topic not in ONOSTopics:
215 checkResult = EventStates().FAIL
216 main.log.warn( "ONOS Check - Topic %s not in leaders on ONOS%s" % ( topic, controller.index ) )
217 # Check node state
218 with controller.CLILock:
219 nodes = controller.CLI.nodes()
220 nodes = json.loads( nodes )
221 ipToState = {}
222 for node in nodes:
223 ipToState[ node[ 'ip' ] ] = node[ 'state' ]
224 for c in main.controllers:
225 if c.isUp() and ipToState[ c.ip ] == 'READY':
226 pass
227 elif not c.isUp() and ipToState[ c.ip ] == 'INACTIVE':
228 pass
229 else:
230 checkResult = EventStates().FAIL
231 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 ] ) )
232 # TODO: check partitions?
233 except ( TypeError, ValueError ):
234 main.log.exception( "ONOS Check - Object not as expected" )
235 return EventStates().FAIL
You Wangdb927a52016-02-26 11:03:28 -0800236 return checkResult
237
238class TrafficCheck( CheckEvent ):
239 def __init__( self ):
240 CheckEvent.__init__( self )
241 self.typeString = main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeString' ]
242 self.typeIndex= int( main.params[ 'EVENT' ][ self.__class__.__name__ ][ 'typeIndex' ] )
243
244 def startCheckEvent( self, args=None ):
245 checkResult = EventStates().PASS
246 pool = []
247 wait = int( main.params[ 'EVENT' ][ 'TrafficCheck' ][ 'pingWait' ] )
248 timeout = int( main.params[ 'EVENT' ][ 'TrafficCheck' ][ 'pingTimeout' ] )
249 dstIPv4List = {}
250 dstIPv6List = {}
251 upHosts = []
252 for host in main.hosts:
253 if host.isUp():
254 upHosts.append( host )
255 for host in upHosts:
256 dstIPv4List[ host.index ] = []
257 dstIPv6List[ host.index ] = []
258 for correspondent in host.correspondents:
259 if not correspondent in upHosts:
260 continue
261 for ipAddress in correspondent.ipAddresses:
262 if ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv6Prefix' ] ) ):
263 dstIPv6List[ host.index ].append( ipAddress )
264 elif ipAddress.startswith( str( main.params[ 'TEST' ][ 'ipv4Prefix' ] ) ):
265 dstIPv4List[ host.index ].append( ipAddress )
266 thread = main.Thread( target=host.handle.pingHostSetAlternative,
267 threadID=main.threadID,
268 name="pingHostSetAlternative",
269 args=[ dstIPv4List[ host.index ], 1 ] )
270 pool.append( thread )
271 thread.start()
272 with main.variableLock:
273 main.threadID += 1
274 for thread in pool:
275 thread.join( 10 )
276 if not thread.result:
277 checkResult = EventStates().FAIL
278 main.log.warn( "Traffic Check - ping failed" )
279
280 if not main.enableIPv6:
281 return checkResult
282 # Check ipv6 ping
283 for host in upHosts:
284 thread = main.Thread( target=host.handle.pingHostSetAlternative,
285 threadID=main.threadID,
286 name="pingHostSetAlternative",
287 args=[ dstIPv6List[ host.index ], 1, True ] )
288 pool.append( thread )
289 thread.start()
290 with main.variableLock:
291 main.threadID += 1
292 for thread in pool:
293 thread.join( 10 )
294 if not thread.result:
295 checkResult = EventStates().FAIL
296 main.log.warn( "Traffic Check - ping6 failed" )
297 return checkResult
298