blob: 79f1d892eee2e7a8a61823a62a768b3d415dd107 [file] [log] [blame]
Jon Hall43060f62020-06-23 13:13:33 -07001#!/usr/bin/env python
2"""
3Copyright 2020 Open Networking Foundation (ONF)
4
5Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
6the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
7or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
8
9TestON is free software: you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation, either version 2 of the License, or
12( at your option ) any later version.
13
14TestON is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with TestON. If not, see <http://www.gnu.org/licenses/>.
21"""
22
23import pexpect
24import types
25import os
26from drivers.common.clidriver import CLI
27
28class StratumOSSwitchDriver( CLI ):
29
30 def __init__( self ):
31 """
32 Initialize client
33 """
34 super( CLI, self ).__init__()
35 self.name = None
36 self.shortName = None
37 self.handle = None
38 self.prompt = "~(/TestON)?#"
39 self.dockerPrompt = "/run/stratum#"
40
41 self.home = "/root"
42 # Local home for functions using scp
43 self.tempDirectory = "/tmp/"
44 self.ports = []
45 self.isup = True
46
47 def connect( self, **connectargs ):
48 """
49 Creates ssh handle for cli.
50 """
51 try:
52 # Parse keys in xml object
53 for key in connectargs:
54 vars( self )[ key ] = connectargs[ key ]
55 # Get the name
56 self.name = self.options[ 'name' ]
57 self.shortName = self.options[ 'shortName' ]
58 # Parse the IP address
59 try:
60 if os.getenv( str( self.ip_address ) ) is not None:
61 self.ip_address = os.getenv( str( self.ip_address ) )
62 # Otherwise is an ip address
63 else:
64 main.log.info( self.name + ": Trying to connect to " + self.ip_address )
65 # Error handling
66 except KeyError:
67 main.log.info( "Invalid host name," + " connecting to local host instead" )
68 self.ip_address = 'localhost'
69 except Exception as inst:
70 main.log.error( "Uncaught exception: " + str( inst ) )
71 self.handle = super( StratumOSSwitchDriver, self ).connect(
72 user_name=self.user_name,
73 ip_address=self.ip_address,
74 port=None,
75 pwd=self.pwd)
76 # Successful connection
77 if self.handle:
78 main.log.info( "Connection successful to the host " + self.user_name + "@" + self.ip_address )
79 self.handle.sendline( "" )
80 self.handle.expect( self.prompt )
81 return main.TRUE
82 # Connection failed
83 else:
84 main.log.error( "Connection failed to the host " + self.user_name + "@" + self.ip_address )
85 main.log.error( "Failed to connect to the Stratum Switch" )
86 return main.FALSE
87 # Error handling
88 except TypeError:
89 main.log.exception( self.name + ": Object not as expected" )
90 return None
91 except pexpect.EOF:
92 main.log.error( self.name + ": EOF exception found" )
93 main.log.error( self.name + ": " + self.handle.before )
94 main.cleanup()
95 main.exit()
96 except Exception:
97 main.log.exception( self.name + ": Uncaught exception!" )
98 main.cleanup()
99 main.exit()
100
101 def disconnect( self ):
102 """
103 Called when Test is complete to disconnect the component handle.
104 """
105 response = main.TRUE
106 try:
107 if self.handle:
108 # Stop the agent
109 self.stopSwitchAgent()
110 main.log.debug( self.name + ": Disconnected" )
111 # Disconnect from the device
112 self.handle.sendline( "" )
113 self.handle.expect( self.prompt )
114 self.handle.sendline( "exit" )
115 self.handle.expect( "closed" )
116 # Errors handling
117 except pexpect.TIMEOUT:
118 main.log.error( self.name + ": pexpect.TIMEOUT found" )
119 main.log.debug( self.handle.before )
120 return main.FALSE
121 except TypeError:
122 main.log.exception( self.name + ": Object not as expected" )
123 response = main.FALSE
124 except pexpect.EOF:
125 main.log.error( self.name + ": EOF exception found" )
126 main.log.error( self.name + ": " + self.handle.before )
127 except ValueError:
128 main.log.exception( "Exception in disconnect of " + self.name )
129 response = main.TRUE
130 except Exception:
131 main.log.exception( self.name + ": Connection failed to the host" )
132 response = main.FALSE
133 return response
134
135 def assignSwController( self, ip, updateConf=True, **kwargs ):
136 """
137 Description:
138 Edit the config file for the switch and upload it to the onos
139 controller to connect the switch and controller
140
141 NOTE that this function is available on all switch drivers,
142 and the name is a hold over from ovs switches.
143 kwargs contains any arguments for other types of switches
144 Required:
145 ip - Ip addresses of controllers. This can be a list or a string.
146 updateConf - whether to pull and update configurations and scripts
147 Return:
148 Returns main.TRUE if the switch is correctly assigned to controllers,
149 otherwise it will return main.FALSE or an appropriate exception(s)
150 """
151 assignResult = main.TRUE
152 onosIp = ""
153 # Parses the controller option
154 # We only need one onos ip
155 try:
156 if isinstance( ip, types.StringType ):
157 onosIp = str( ip )
158 elif isinstance( ip, types.ListType ):
159 onosIp = ip[ 0 ]
160 else:
161 main.log.error( self.name + ": Invalid controller ip address" )
162 return main.FALSE
163 if updateConf:
164 self.setupContainer()
165 main.ONOSbench.onosNetCfg( onosIp, self.options[ 'onosConfigPath' ], self.options[ 'onosConfigFile' ] )
166
167 assignResult = self.startSwitchAgent()
168 if not assignResult:
169 self.isup = False
170 else:
171 self.isup = True
172 # Done return true
173 return assignResult
174 # Errors handling
175 except pexpect.TIMEOUT:
176 main.log.error( self.name + ": pexpect.TIMEOUT found" )
177 return main.FALSE
178 except pexpect.EOF:
179 main.log.error( self.name + ": EOF exception found" )
180 main.log.error( self.name + ": " + self.handle.before )
181 main.cleanAndExit()
182 except Exception:
183 main.log.exception( self.name + ": Uncaught exception!" )
184 main.cleanAndExit()
185
186 def setupContainer( self ):
187 """
188 Prepare for the container to be run. Includes pulling scripts
189 and modifying them
190 """
191 try:
192 #TODO Remove hardcoding
193 main.log.info( "Creating working directory" )
194 self.handle.sendline( "mkdir TestON" )
195 self.handle.expect( self.prompt )
196 self.handle.sendline( "cd TestON" )
197 self.handle.expect( self.prompt )
198
199 main.log.info( "Getting start container script" )
200 # TODO: Parameterize this
201 self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/bin/barefoot/docker/start-stratum-container.sh" )
202 self.handle.expect( self.prompt )
203 main.log.info( "Modify start container script" )
204 self.handle.sendline( "sed -i '/--privileged/a \ --name stratum \\\\' start-stratum-container.sh" )
205 self.handle.expect( self.prompt )
206 #self.handle.sendline( "sed -i '/LOG_DIR:\/var\/log\/stratum/a \ --entrypoint /bin/bash \\\\' start-stratum-container.sh" )
207 #self.handle.expect( self.prompt )
208 # TODO: Add docker pull command to the start-stratum-container.sh script
209
210 main.log.info( "Getting chassis config" )
211 # TODO: Parameterize this
212 self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/config/x86-64-accton-wedge100bf-32x-r0/chassis_config.pb.txt" )
213 self.handle.expect( self.prompt )
214 main.log.info( "Modify chassis config" )
215 # TODO: Parameterize this
216 self.handle.sendline( "sed -i '$!N;s/\(port: [5|6]\\n\ speed_bps: \)\([0-9]*\)/\\1 40000000000/;P;D' chassis_config.pb.txt" )
217 self.handle.expect( self.prompt )
218 self.handle.sendline( "export CHASSIS_CONFIG=~/TestON/chassis_config.pb.txt" )
219 self.handle.expect( self.prompt )
220 self.handle.sendline( "chmod +x start-stratum-container.sh" )
221 self.handle.expect( self.prompt )
222 except pexpect.TIMEOUT:
223 main.log.error( self.name + ": pexpect.TIMEOUT found" )
224 main.log.debug( self.handle.before )
225 return main.FALSE
226 except pexpect.EOF:
227 main.log.error( self.name + ": EOF exception found" )
228 main.log.error( self.name + ": " + self.handle.before )
229 main.cleanAndExit()
230 except Exception:
231 main.log.exception( self.name + ": Uncaught exception!" )
232 main.cleanAndExit()
233
234 def startSwitchAgent( self ):
235 """
236 Start the stratum agent on the device
237 """
238 try:
239 main.log.info( "Starting switch agent" )
240 self.handle.sendline( "./start-stratum-container.sh --bf-sim" )
241 self.handle.expect( "Chassis config pushed successfully." )
242 return main.TRUE
243 except pexpect.TIMEOUT:
244 main.log.error( self.name + ": pexpect.TIMEOUT found" )
245 main.log.debug( self.handle.before )
246 return main.FALSE
247 except pexpect.EOF:
248 main.log.error( self.name + ": EOF exception found" )
249 main.log.error( self.name + ": " + self.handle.before )
250 main.cleanAndExit()
251 except Exception:
252 main.log.exception( self.name + ": Uncaught exception!" )
253 main.cleanAndExit()
254
255 def stopSwitchAgent( self ):
256 """
257 Stop the strratum agent on the device
258 """
259 try:
260 main.log.info( self.name + ": stopping Stratum Switch agent" )
261 while True:
262 self.handle.sendline( "" )
263 i = self.handle.expect( [ self.prompt, self.dockerPrompt, pexpect.TIMEOUT, "Aborted at" ] )
264 if i == 2:
265 self.handle.send( "\x03" ) # ctrl-c to close switch agent
266 self.handle.sendline( "" )
267 elif i == 1:
268 self.handle.sendline( "exit" ) # exit docker
269 self.handle.expect( self.prompt )
270 elif i == 0:
271 self.handle.sendline( "docker stop stratum" ) # Make sure the container is stopped
272 self.handle.expect( self.prompt )
273 main.log.debug( self.name + ": Stratum Switch agent stopped" )
274 return
275 elif i == 3:
276 main.log.error( "Stratum agent aborted" )
277 # TODO: Find and save any extra logs
278 output = self.handle.before + self.handle.after
279 self.handle.sendline( "" )
280 self.handle.expect( self.prompt )
281 output += self.handle.before + self.handle.after
282 main.log.debug( output )
283 main.cleanAndExit()
284 except pexpect.TIMEOUT:
285 main.log.error( self.name + ": pexpect.TIMEOUT found" )
286 main.log.debug( self.handle.before )
287 return main.FALSE
288 except pexpect.EOF:
289 main.log.error( self.name + ": EOF exception found" )
290 main.log.error( self.name + ": " + self.handle.before )
291 main.cleanAndExit()
292 except Exception:
293 main.log.exception( self.name + ": Uncaught exception!" )
294 main.cleanAndExit()