blob: 2a81987f6aaaf95ccb294fabe4866e3b81b8784b [file] [log] [blame]
Devin Lim142b5342017-07-20 15:22:39 -07001"""
2Copyright 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"""
Devin Lim58046fa2017-07-05 16:55:00 -070021import time
22import re
23import imp
24import json
25class Topology:
26
27 def __init__( self ):
28 self.default = ''
Devin Lim142b5342017-07-20 15:22:39 -070029
Devin Lim58046fa2017-07-05 16:55:00 -070030 """
31 These functions can be used for topology comparisons
32 """
Devin Lim142b5342017-07-20 15:22:39 -070033 def getAll( self, function, needRetry=False, kwargs={}, inJson=False ):
Devin Lim58046fa2017-07-05 16:55:00 -070034 """
Devin Lim142b5342017-07-20 15:22:39 -070035 Description:
36 get all devices/links/hosts/ports of the onosCli
37 Required:
38 * function - name of the function
39 * needRetry - it will retry if this is true.
40 * kwargs - kwargs of the function
41 * inJson - True if want it in Json form
42 Returns:
43 Returns the list of the result.
Devin Lim58046fa2017-07-05 16:55:00 -070044 """
Devin Lim142b5342017-07-20 15:22:39 -070045 returnList = []
Devin Lim58046fa2017-07-05 16:55:00 -070046 threads = []
Jon Hallca319892017-06-15 15:25:22 -070047 for ctrl in main.Cluster.active():
Devin Lim142b5342017-07-20 15:22:39 -070048 func = getattr( ctrl.CLI, function )
49 t = main.Thread( target=utilities.retry if needRetry else func,
50 name= function + "-" + str( ctrl ),
51 args=[ func, [ None ] ] if needRetry else [],
Devin Lim58046fa2017-07-05 16:55:00 -070052 kwargs=kwargs )
53 threads.append( t )
54 t.start()
55
56 for t in threads:
57 t.join()
58 if inJson:
59 try:
Devin Lim142b5342017-07-20 15:22:39 -070060 returnList.append( json.loads( t.result ) )
Devin Lim58046fa2017-07-05 16:55:00 -070061 except ( ValueError, TypeError ):
62 main.log.exception( "Error parsing hosts results" )
63 main.log.error( repr( t.result ) )
Devin Lim142b5342017-07-20 15:22:39 -070064 returnList.append( None )
Devin Lim58046fa2017-07-05 16:55:00 -070065 else:
Devin Lim142b5342017-07-20 15:22:39 -070066 returnList.append( t.result )
67 return returnList
Devin Lim58046fa2017-07-05 16:55:00 -070068
69 def compareDevicePort( self, Mininet, controller, mnSwitches, devices, ports ):
Devin Lim142b5342017-07-20 15:22:39 -070070 """
71 Description:
72 compares the devices and port of the onos to the mininet.
73 Required:
74 * Mininet - mininet driver to use
75 * controller - controller position of the devices
76 * mnSwitches - switches of mininet
77 * devices - devices of the onos
78 * ports - ports of the onos
79 Returns:
80 Returns main.TRUE if the results are matching else
81 Returns main.FALSE
82 """
Devin Lim58046fa2017-07-05 16:55:00 -070083 if devices[ controller ] and ports[ controller ] and \
84 "Error" not in devices[ controller ] and \
85 "Error" not in ports[ controller ]:
86 try:
87 currentDevicesResult = Mininet.compareSwitches(
88 mnSwitches,
89 json.loads( devices[ controller ] ),
90 json.loads( ports[ controller ] ) )
Jon Hallca319892017-06-15 15:25:22 -070091 except ( TypeError, ValueError ):
Devin Lim58046fa2017-07-05 16:55:00 -070092 main.log.error(
Jon Hallca319892017-06-15 15:25:22 -070093 "Could not load json: {0} or {1}".format( str( devices[ controller ] ),
94 str( ports[ controller ] ) ) )
Devin Lim58046fa2017-07-05 16:55:00 -070095 currentDevicesResult = main.FALSE
96 else:
97 currentDevicesResult = main.FALSE
98 return currentDevicesResult
99
100 def compareBase( self, compareElem, controller, compareF, compareArg ):
Devin Lim142b5342017-07-20 15:22:39 -0700101 """
102 Description:
103 compares the links/hosts of the onos to the mininet.
104 Required:
105 * compareElem - list of links/hosts of the onos
106 * controller - controller position of the devices
107 * compareF - function of the mininet that will compare the
108 results
109 * compareArg - arg of the compareF.
110 Returns:
111 Returns main.TRUE if the results are matching else
112 Returns main.FALSE
113 """
Devin Lim58046fa2017-07-05 16:55:00 -0700114 if compareElem[ controller ] and "Error" not in compareElem[ controller ]:
115 try:
116 if isinstance( compareArg, list ):
117 compareArg.append( json.loads( compareElem[ controller ] ) )
118 else:
119 compareArg = [compareArg, json.loads( compareElem[ controller ] ) ]
120
121 currentCompareResult = compareF( *compareArg )
122 except(TypeError, ValueError):
123 main.log.error(
124 "Could not load json: {0} or {1}".format( str( compareElem[ controller ] ) ) )
125 currentCompareResult = main.FALSE
126 else:
127 currentCompareResult = main.FALSE
128
129 return currentCompareResult
130
131 def compareTopos( self, Mininet, attempts=1 ):
Devin Lim142b5342017-07-20 15:22:39 -0700132 """
133 Description:
134 compares the links and hosts and switches of the onos to the mininet.
135 Required:
136 * Mininet - Mininet driver to use.
137 * attempts - number of attempts to compare in case
138 the result is different after a certain time.
139 Returns:
140 Returns main.TRUE if the results are matching else
141 Returns main.FALSE
142 """
Devin Lim58046fa2017-07-05 16:55:00 -0700143 main.case( "Compare ONOS Topology view to Mininet topology" )
144 main.caseExplanation = "Compare topology elements between Mininet" +\
145 " and ONOS"
146 main.log.info( "Gathering topology information from Mininet" )
147 devicesResults = main.FALSE # Overall Boolean for device correctness
148 linksResults = main.FALSE # Overall Boolean for link correctness
149 hostsResults = main.FALSE # Overall Boolean for host correctness
150 deviceFails = [] # Nodes where devices are incorrect
151 linkFails = [] # Nodes where links are incorrect
152 hostFails = [] # Nodes where hosts are incorrect
153
154 mnSwitches = Mininet.getSwitches()
155 mnLinks = Mininet.getLinks()
156 mnHosts = Mininet.getHosts()
157
158 main.step( "Comparing Mininet topology to ONOS topology" )
159
160 while ( attempts >= 0 ) and\
161 ( not devicesResults or not linksResults or not hostsResults ):
162 main.log.info( "Sleeping {} seconds".format( 2 ) )
163 time.sleep( 2 )
164 if not devicesResults:
Devin Lim142b5342017-07-20 15:22:39 -0700165 devices = self.getAll( "devices", False )
166 ports = self.getAll( "ports", False )
Devin Lim58046fa2017-07-05 16:55:00 -0700167 devicesResults = main.TRUE
168 deviceFails = [] # Reset for each failed attempt
169 if not linksResults:
Devin Lim142b5342017-07-20 15:22:39 -0700170 links = self.getAll( "links", False )
Devin Lim58046fa2017-07-05 16:55:00 -0700171 linksResults = main.TRUE
172 linkFails = [] # Reset for each failed attempt
173 if not hostsResults:
Devin Lim142b5342017-07-20 15:22:39 -0700174 hosts = self.getAll( "hosts", False )
Devin Lim58046fa2017-07-05 16:55:00 -0700175 hostsResults = main.TRUE
176 hostFails = [] # Reset for each failed attempt
177
178 # Check for matching topology on each node
Devin Lim142b5342017-07-20 15:22:39 -0700179 for controller in main.Cluster.getRunningPos():
Devin Lim58046fa2017-07-05 16:55:00 -0700180 controllerStr = str( controller + 1 ) # ONOS node number
181 # Compare Devices
182 currentDevicesResult = self.compareDevicePort( Mininet, controller,
Jon Hallca319892017-06-15 15:25:22 -0700183 mnSwitches,
184 devices, ports )
Devin Lim58046fa2017-07-05 16:55:00 -0700185 if not currentDevicesResult:
186 deviceFails.append( controllerStr )
187 devicesResults = devicesResults and currentDevicesResult
188 # Compare Links
189 currentLinksResult = self.compareBase( links, controller,
Jon Hallca319892017-06-15 15:25:22 -0700190 Mininet.compareLinks,
191 [ mnSwitches, mnLinks ] )
Devin Lim58046fa2017-07-05 16:55:00 -0700192 if not currentLinksResult:
193 linkFails.append( controllerStr )
194 linksResults = linksResults and currentLinksResult
195 # Compare Hosts
196 currentHostsResult = self.compareBase( hosts, controller,
197 Mininet.compareHosts,
198 mnHosts )
199 if not currentHostsResult:
200 hostFails.append( controllerStr )
201 hostsResults = hostsResults and currentHostsResult
202 # Decrement Attempts Remaining
203 attempts -= 1
204
205 utilities.assert_equals( expect=[],
206 actual=deviceFails,
207 onpass="ONOS correctly discovered all devices",
208 onfail="ONOS incorrectly discovered devices on nodes: " +
209 str( deviceFails ) )
210 utilities.assert_equals( expect=[],
211 actual=linkFails,
212 onpass="ONOS correctly discovered all links",
213 onfail="ONOS incorrectly discovered links on nodes: " +
214 str( linkFails ) )
215 utilities.assert_equals( expect=[],
216 actual=hostFails,
217 onpass="ONOS correctly discovered all hosts",
218 onfail="ONOS incorrectly discovered hosts on nodes: " +
219 str( hostFails ) )
220 topoResults = hostsResults and linksResults and devicesResults
221 utilities.assert_equals( expect=main.TRUE,
222 actual=topoResults,
223 onpass="ONOS correctly discovered the topology",
224 onfail="ONOS incorrectly discovered the topology" )
Devin Lim142b5342017-07-20 15:22:39 -0700225 return topoResults