blob: 5c057bfa723b323a8877590d11fa5c4bc97112de [file] [log] [blame]
Jon Hall2c8959e2016-12-16 12:17:34 -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/>.
Jeremy Ronquillob27ce4c2017-07-17 12:41:28 -070020
Jon Hall2c8959e2016-12-16 12:17:34 -080021Functions for the vpls tests
22"""
23import time
24import json
25
Jon Halled258232017-05-24 17:30:18 -070026
Jon Hall2c8959e2016-12-16 12:17:34 -080027def sanitizeConfig( config ):
28 """
29 Take a python json object for vpls config and normalize it.
30 Things it does:
31 Converts all strings to the same format
32 Make sure each network has an encapsulation key:value
33 Makes sure encapsulation type is all uppercase
34 Make sure an empty list of interfaces is formated consistently
35 Sorts the list of interfaces
Jon Hall0dccfa52017-05-18 11:21:11 -070036 Sorts the list of networks
Jon Hall2c8959e2016-12-16 12:17:34 -080037 """
38 # Convert to same string formats
39 config = json.loads( json.dumps( config ) )
40 for network in config:
41 encap = network.get( 'encapsulation', None )
42 if encap is None:
43 encap = "NONE"
44 network[ 'encapsulation' ] = encap.upper()
45 ifaces = network.get( 'interfaces' )
Jon Halled258232017-05-24 17:30:18 -070046 if ifaces == [ '' ]:
Jon Hall2c8959e2016-12-16 12:17:34 -080047 ifaces = []
48 else:
49 ifaces = sorted( ifaces )
Jon Halled258232017-05-24 17:30:18 -070050 network[ 'interfaces' ] = ifaces
51 config = sorted( config, key=lambda k: k[ 'name' ] )
Jon Hall2c8959e2016-12-16 12:17:34 -080052 return config
53
Jon Halled258232017-05-24 17:30:18 -070054
Jon Hall2c8959e2016-12-16 12:17:34 -080055def verify( main ):
56 """
57 Runs some tests to verify the vpls configurations.
58 - Compare sent vpls network configuration to what is stored in each:
59 - ONOS network configuration
60 - ONOS VPLS application configuration
61 - Ping between each pair of hosts to check connectivity
62
63 NOTE: This requires the expected/sent network config json for the vpls
64 application be stored in main.vplsConfig
65 """
66 # Variables
Jon Halled258232017-05-24 17:30:18 -070067 app = main.params[ 'vpls' ][ 'name' ]
Devin Lim6301b742017-08-07 11:00:21 -070068 pprint = main.Cluster.active( 0 ).REST.pprint
Jon Halled258232017-05-24 17:30:18 -070069 SLEEP = int( main.params[ 'SLEEP' ][ 'netcfg' ] )
Jon Hall2c8959e2016-12-16 12:17:34 -080070
71 main.step( "Check network configurations for vpls application" )
72 clusterResult = True
Devin Lim6301b742017-08-07 11:00:21 -070073 for ctrl in main.Cluster.active():
Jon Hall2c8959e2016-12-16 12:17:34 -080074 result = False
Devin Lim6301b742017-08-07 11:00:21 -070075 getVPLS = utilities.retry( f=ctrl.REST.getNetCfg,
Jeremy Ronquillo4a30ffe2017-06-07 11:36:35 -070076 retValue=False,
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070077 kwargs={ "subjectClass": "apps", "subjectKey": app },
Jeremy Ronquillo4a30ffe2017-06-07 11:36:35 -070078 sleep=SLEEP )
Jon Hall2c8959e2016-12-16 12:17:34 -080079 onosCfg = json.loads( getVPLS ).get( 'vpls' ).get( 'vplsList' )
80 onosCfg = pprint( sanitizeConfig( onosCfg ) )
81 sentCfg = pprint( sanitizeConfig( main.vplsConfig ) )
82 result = onosCfg == sentCfg
83 if result:
84 main.log.info( "ONOS NetCfg matches what was sent" )
85 else:
86 clusterResult = False
87 main.log.error( "ONOS NetCfg doesn't match what was sent" )
88 main.log.debug( "ONOS config: {}".format( onosCfg ) )
89 main.log.debug( "Sent config: {}".format( sentCfg ) )
90 utilities.assert_equals( expect=True,
91 actual=clusterResult,
92 onpass="Net Cfg added for vpls",
93 onfail="Net Cfg not added for vpls" )
94
95 main.step( "Check vpls app configurations" )
96 clusterResult = True
Devin Lim6301b742017-08-07 11:00:21 -070097 for ctrl in main.Cluster.active():
Jon Hall2c8959e2016-12-16 12:17:34 -080098 result = False
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -070099 # TODO Read from vpls show and match to pushed json
Devin Lim6301b742017-08-07 11:00:21 -0700100 vpls = ctrl.CLI.parseVplsShow()
Jon Hall2c8959e2016-12-16 12:17:34 -0800101 parsedVpls = pprint( sanitizeConfig( vpls ) )
102 sentVpls = pprint( sanitizeConfig( main.vplsConfig ) )
103 result = parsedVpls == sentVpls
104 if result:
105 main.log.info( "VPLS config matches sent NetCfg" )
106 else:
107 clusterResult = False
108 main.log.error( "VPLS config doesn't match sent NetCfg" )
109 main.log.debug( "ONOS config: {}".format( parsedVpls ) )
110 main.log.debug( "Sent config: {}".format( sentVpls ) )
111 utilities.assert_equals( expect=True,
112 actual=clusterResult,
113 onpass="VPLS successfully configured",
114 onfail="VPLS not configured correctly" )
115
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700116 checkIntentState( main )
117
Jon Hall2c8959e2016-12-16 12:17:34 -0800118 main.step( "Check connectivity" )
119 connectivityCheck = True
Jon Halled258232017-05-24 17:30:18 -0700120 hosts = int( main.params[ 'vpls' ][ 'hosts' ] )
Jon Hall2c8959e2016-12-16 12:17:34 -0800121 networks = []
122 for network in main.vplsConfig:
123 nodes = network.get( 'interfaces', None )
124 if nodes:
125 networks.append( nodes )
126 for i in range( 1, hosts + 1 ):
127 src = "h" + str( i )
128 for j in range( 1, hosts + 1 ):
129 if j == i:
130 continue
131 dst = "h" + str( j )
132 pingResult = main.Mininet1.pingHost( SRC=src, TARGET=dst )
133 expected = main.FALSE
134 for network in networks:
135 if src in network and dst in network:
136 expected = main.TRUE
137 break
138 if pingResult != expected:
139 connectivityCheck = False
140 main.log.error( "%s <-> %s: %s; Expected: %s" %
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700141 ( src, dst, pingResult, expected ) )
Jon Hall2c8959e2016-12-16 12:17:34 -0800142 utilities.assert_equals( expect=True,
143 actual=connectivityCheck,
144 onpass="Connectivity is as expected",
145 onfail="Connectivity is not as expected" )
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700146
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700147# TODO: if encapsulation is set, look for that
148# TODO: can we look at the intent keys?
149
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700150
151def checkIntentState( main, bl=[] ):
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700152 # Print the intent states
Devin Lim6301b742017-08-07 11:00:21 -0700153 intents = main.Cluster.active( 0 ).CLI.intents()
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700154 count = 0
155 while count <= 5:
156 installedCheck = True
157 try:
158 i = 1
159 for intent in json.loads( intents ):
160 state = intent.get( 'state', None )
161 if "INSTALLED" not in state or ( "WITHDRAWN" not in state and "h" + str( i ) in bl ):
162 installedCheck = False
163 i += 1
164 except ( ValueError, TypeError ):
165 main.log.exception( "Error parsing intents" )
166 if installedCheck:
167 break
168 count += 1
169 return installedCheck
170
171
172def getVplsHashtable( main, bl=[] ):
173 """
174 Returns a hashtable of vpls to hosts
175 """
176 result = {}
177 vplsConfig = main.vplsConfig
178 for v in vplsConfig:
Jeremy Ronquillo23fb2162017-09-15 14:59:57 -0700179 interfaces = v[ 'interfaces' ][ : ]
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700180 for i in bl:
181 if i in interfaces:
182 interfaces.remove( i )
183 result[ v[ 'name' ] ] = interfaces
184 return result
185
186
187def testConnectivityVpls( main, blacklist=[], isNodeUp=True ):
188
189 # Can't do intent check when onos node is stopped/killed yet
190 if isNodeUp:
191 main.step( "Check intent states" )
192 intentsCheck = utilities.retry( f=checkIntentState,
193 retValue=False,
194 args=( main, blacklist ),
195 sleep=main.timeSleep,
196 attempts=main.numAttempts )
197
198 utilities.assert_equals( expect=True,
199 actual=intentsCheck,
200 onpass="All Intents in installed state",
201 onfail="Not all Intents in installed state" )
202
203 main.step( "Testing connectivity..." )
204
205 vplsHashtable = getVplsHashtable( main, blacklist )
206 main.log.debug( "vplsHashtable: " + str( vplsHashtable ) )
207 result = True
208 for key in vplsHashtable:
209 pingResult = utilities.retry( f=main.Mininet1.pingallHosts,
210 retValue=False,
211 args=( vplsHashtable[ key ], ),
212 sleep=main.timeSleep,
213 attempts=main.numAttempts )
214 result = result and pingResult
215
216 utilities.assert_equals( expect=main.TRUE, actual=result,
217 onpass="Connectivity succeeded.",
218 onfail="Connectivity failed." )
219 return result
220
221
222def compareApps( main ):
223 result = True
224 first = None
Devin Lim6301b742017-08-07 11:00:21 -0700225 for ctrl in main.Cluster.active():
226 currentApps = ctrl.CLI.apps( summary=True, active=True )
Jeremy Ronquillo3008aa32017-07-07 15:38:57 -0700227 if not result:
228 first = currentApps
229 else:
230 result = result and ( currentApps == first )
231 return result