blob: 3eae155bb271dac046c1647be1723f432a59ab78 [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 )
Jon Hall43060f62020-06-23 13:13:33 -0700206 # TODO: Add docker pull command to the start-stratum-container.sh script
207
208 main.log.info( "Getting chassis config" )
209 # TODO: Parameterize this
Jon Hall39570262020-11-17 12:18:19 -0800210 filename = "~/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa"
211 main.ONOSbench.secureCopy( self.user_name, self.ip_address, filename, "~/TestON/chassis_config.pb.txt", pwd=self.pwd, direction="to" )
Jon Hall43060f62020-06-23 13:13:33 -0700212 main.log.info( "Modify chassis config" )
213 # TODO: Parameterize this
Jon Hall43060f62020-06-23 13:13:33 -0700214 self.handle.sendline( "export CHASSIS_CONFIG=~/TestON/chassis_config.pb.txt" )
215 self.handle.expect( self.prompt )
Jon Hall39570262020-11-17 12:18:19 -0800216 #self.handle.sendline( "export DOCKER_IMAGE=registry.aetherproject.org/tost/stratum-bfrt" )
217 self.handle.sendline( "export DOCKER_IMAGE=stratumproject/stratum-bf" )
218 self.handle.expect( self.prompt )
219 self.handle.sendline( "export DOCKER_IMAGE_TAG=9.2.0" )
220 self.handle.expect( self.prompt )
Jon Hall43060f62020-06-23 13:13:33 -0700221 self.handle.sendline( "chmod +x start-stratum-container.sh" )
222 self.handle.expect( self.prompt )
223 except pexpect.TIMEOUT:
224 main.log.error( self.name + ": pexpect.TIMEOUT found" )
225 main.log.debug( self.handle.before )
226 return main.FALSE
227 except pexpect.EOF:
228 main.log.error( self.name + ": EOF exception found" )
229 main.log.error( self.name + ": " + self.handle.before )
230 main.cleanAndExit()
231 except Exception:
232 main.log.exception( self.name + ": Uncaught exception!" )
233 main.cleanAndExit()
234
235 def startSwitchAgent( self ):
236 """
237 Start the stratum agent on the device
238 """
239 try:
240 main.log.info( "Starting switch agent" )
Jon Hall39570262020-11-17 12:18:19 -0800241 self.handle.sendline( "./start-stratum-container.sh --bf-sim --bf-switchd-background=false" )
Jon Hall43060f62020-06-23 13:13:33 -0700242 self.handle.expect( "Chassis config pushed successfully." )
243 return main.TRUE
244 except pexpect.TIMEOUT:
245 main.log.error( self.name + ": pexpect.TIMEOUT found" )
246 main.log.debug( self.handle.before )
247 return main.FALSE
248 except pexpect.EOF:
249 main.log.error( self.name + ": EOF exception found" )
250 main.log.error( self.name + ": " + self.handle.before )
251 main.cleanAndExit()
252 except Exception:
253 main.log.exception( self.name + ": Uncaught exception!" )
254 main.cleanAndExit()
255
256 def stopSwitchAgent( self ):
257 """
258 Stop the strratum agent on the device
259 """
260 try:
261 main.log.info( self.name + ": stopping Stratum Switch agent" )
262 while True:
263 self.handle.sendline( "" )
264 i = self.handle.expect( [ self.prompt, self.dockerPrompt, pexpect.TIMEOUT, "Aborted at" ] )
265 if i == 2:
266 self.handle.send( "\x03" ) # ctrl-c to close switch agent
267 self.handle.sendline( "" )
268 elif i == 1:
269 self.handle.sendline( "exit" ) # exit docker
270 self.handle.expect( self.prompt )
271 elif i == 0:
272 self.handle.sendline( "docker stop stratum" ) # Make sure the container is stopped
273 self.handle.expect( self.prompt )
274 main.log.debug( self.name + ": Stratum Switch agent stopped" )
275 return
276 elif i == 3:
277 main.log.error( "Stratum agent aborted" )
278 # TODO: Find and save any extra logs
279 output = self.handle.before + self.handle.after
280 self.handle.sendline( "" )
281 self.handle.expect( self.prompt )
282 output += self.handle.before + self.handle.after
283 main.log.debug( output )
284 main.cleanAndExit()
285 except pexpect.TIMEOUT:
286 main.log.error( self.name + ": pexpect.TIMEOUT found" )
287 main.log.debug( self.handle.before )
288 return main.FALSE
289 except pexpect.EOF:
290 main.log.error( self.name + ": EOF exception found" )
291 main.log.error( self.name + ": " + self.handle.before )
292 main.cleanAndExit()
293 except Exception:
294 main.log.exception( self.name + ": Uncaught exception!" )
295 main.cleanAndExit()