blob: e14a38db14e3c3c369af85e383c3db20865fdb0f [file] [log] [blame]
Pier6a0c4de2018-03-18 16:01:30 -07001#!/usr/bin/env python
2"""
3Copyright 2018 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 re
Pier6a0c4de2018-03-18 16:01:30 -070025import os
You Wang4cc61912018-08-28 10:10:58 -070026from drivers.common.cli.emulator.scapyclidriver import ScapyCliDriver
Pier6a0c4de2018-03-18 16:01:30 -070027
You Wang4cc61912018-08-28 10:10:58 -070028class HostDriver( ScapyCliDriver ):
Pier6a0c4de2018-03-18 16:01:30 -070029 """
30 This class is created as a standalone host driver.
31 """
32 def __init__( self ):
33 super( HostDriver, self ).__init__()
34 self.handle = self
35 self.name = None
36 self.shortName = None
You Wangb1665b52019-02-01 15:49:48 -080037 self.interfaces = []
Pier6a0c4de2018-03-18 16:01:30 -070038 self.home = None
You Wang4cc61912018-08-28 10:10:58 -070039 self.inband = False
40 self.prompt = "\$"
41 self.scapyPrompt = ">>>"
Pier6a0c4de2018-03-18 16:01:30 -070042
43 def connect( self, **connectargs ):
44 """
45 Creates ssh handle for host.
46 NOTE:
47 The ip_address would come from the topo file using the host tag, the
48 value can be an environment variable as well as a "localhost" to get
49 the ip address needed to ssh to the "bench"
50 """
51 try:
52 for key in connectargs:
53 vars( self )[ key ] = connectargs[ key ]
54 self.name = self.options[ 'name' ]
55 self.shortName = self.options[ 'shortName' ]
You Wangb1665b52019-02-01 15:49:48 -080056 self.interfaces.append( { 'ips': [ self.options[ 'ip' ] ],
57 'isUp': True,
58 'mac': self.options[ 'mac' ],
Jon Hall43060f62020-06-23 13:13:33 -070059 'name': self.options.get( 'interfaceName', None ) } )
Pier6a0c4de2018-03-18 16:01:30 -070060
61 try:
62 if os.getenv( str( self.ip_address ) ) is not None:
63 self.ip_address = os.getenv( str( self.ip_address ) )
64 else:
65 main.log.info( self.name +
66 ": Trying to connect to " +
67 self.ip_address )
68 except KeyError:
69 main.log.info( "Invalid host name," +
70 " connecting to local host instead" )
71 self.ip_address = 'localhost'
72 except Exception as inst:
73 main.log.error( "Uncaught exception: " + str( inst ) )
74
75 self.handle = super(
76 HostDriver,
77 self ).connect(
78 user_name=self.user_name,
79 ip_address=self.ip_address,
80 port=None,
81 pwd=self.pwd )
82
83 if self.handle:
84 main.log.info( "Connection successful to the " +
85 self.user_name +
86 "@" +
87 self.ip_address )
88 self.handle.sendline( "" )
89 self.handle.expect( self.prompt )
90 return main.TRUE
91 else:
92 main.log.error( "Connection failed to " +
93 self.user_name +
94 "@" +
95 self.ip_address )
96 return main.FALSE
97 except pexpect.EOF:
98 main.log.error( self.name + ": EOF exception found" )
99 main.log.error( self.name + ": " + self.handle.before )
100 main.cleanAndExit()
101 except Exception:
102 main.log.exception( self.name + ": Uncaught exception!" )
103 main.cleanAndExit()
104
105 def disconnect( self, **connectargs ):
106 """
107 Called when test is complete to disconnect the handle.
108 """
109 response = main.TRUE
110 try:
111 if self.handle:
112 # Disconnect from the host
You Wangb1665b52019-02-01 15:49:48 -0800113 if not self.options[ 'inband' ] == 'True':
114 self.handle.sendline( "" )
115 self.handle.expect( self.prompt )
116 self.handle.sendline( "exit" )
117 i = self.handle.expect( [ "closed", pexpect.TIMEOUT ] )
118 if i == 1:
119 main.log.error( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700120 main.log.error( self.name + ": response: " + str( self.handle.before ) )
You Wangb1665b52019-02-01 15:49:48 -0800121 else:
122 self.handle.sendline( "" )
123 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ], timeout=2 )
124 if i == 1:
125 main.log.warn( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700126 main.log.warn( self.name + ": response: " + str( self.handle.before ) )
You Wangb1665b52019-02-01 15:49:48 -0800127 self.handle.sendline( "exit" )
128 i = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=2 )
129 if i == 1:
130 main.log.warn( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700131 main.log.warn( self.name + ": response: " + str( self.handle.before ) )
You Wangb1665b52019-02-01 15:49:48 -0800132 return main.TRUE
Pier6a0c4de2018-03-18 16:01:30 -0700133 except TypeError:
134 main.log.exception( self.name + ": Object not as expected" )
135 response = main.FALSE
136 except pexpect.EOF:
137 main.log.error( self.name + ": EOF exception found" )
138 main.log.error( self.name + ": " + self.handle.before )
139 except ValueError:
140 main.log.exception( "Exception in disconnect of " + self.name )
141 response = main.TRUE
142 except Exception:
143 main.log.exception( self.name + ": Connection failed to the host" )
144 response = main.FALSE
145 return response
146
You Wang4cc61912018-08-28 10:10:58 -0700147 def connectInband( self ):
148 """
149 ssh to the host using its data plane IP
150 """
151 try:
152 if not self.options[ 'inband' ] == 'True':
153 main.log.info( "Skip connecting the host via data plane" )
154 return main.TRUE
155 self.handle.sendline( "" )
156 self.handle.expect( self.prompt )
157 self.handle.sendline( "ssh {}@{}".format( self.options[ 'username' ],
158 self.options[ 'ip' ] ) )
159 i = self.handle.expect( [ "password:|Password:", self.prompt, pexpect.TIMEOUT ], timeout=30 )
160 if i == 0:
161 self.handle.sendline( self.options[ 'password' ] )
162 j = self.handle.expect( [ "password:|Password:", self.prompt, pexpect.TIMEOUT ], timeout=10 )
163 if j != 1:
164 main.log.error( "Incorrect password" )
165 return main.FALSE
166 elif i == 1:
167 main.log.info( "Password not required logged in" )
168 else:
169 main.log.error( "Failed to connect to the host" )
170 return main.FALSE
171 self.inband = True
172 return main.TRUE
173 except KeyError:
174 main.log.error( self.name + ": host component not as expected" )
175 main.log.error( self.name + ": " + self.handle.before )
176 return main.FALSE
177 except pexpect.EOF:
178 main.log.error( self.name + ": EOF exception found" )
179 main.log.error( self.name + ": " + self.handle.before )
180 return main.FALSE
181 except Exception:
182 main.log.exception( self.name + ": Uncaught exception!" )
183 main.log.error( self.name + ": " + self.handle.before )
184 return main.FALSE
185
186 def disconnectInband( self ):
187 """
188 Terminate the ssh connection to the host's data plane IP
189 """
190 try:
191 if not self.options[ 'inband' ] == 'True':
192 main.log.info( "Skip disconnecting the host via data plane" )
193 return main.TRUE
194 self.handle.sendline( "" )
You Wangb1665b52019-02-01 15:49:48 -0800195 self.handle.expect( self.prompt, timeout=2 )
You Wang4cc61912018-08-28 10:10:58 -0700196 self.handle.sendline( "exit" )
197 i = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=2 )
198 if i == 1:
199 main.log.error( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700200 main.log.error( self.name + ": response: " + str( self.handle.before ) )
You Wang4cc61912018-08-28 10:10:58 -0700201 return main.TRUE
202 except pexpect.EOF:
203 main.log.error( self.name + ": EOF exception found" )
204 main.log.error( self.name + ": " + self.handle.before )
205 return main.FALSE
206 except Exception:
207 main.log.exception( self.name + ": Uncaught exception!" )
208 main.log.error( self.name + ": " + self.handle.before )
209 return main.FALSE
210
Jon Hall43060f62020-06-23 13:13:33 -0700211 def ping( self, dst, ipv6=False, interface=None, wait=3 ):
Pier6a0c4de2018-03-18 16:01:30 -0700212 """
213 Description:
214 Ping from this host to another
215 Required:
216 dst: IP address of destination host
217 Optional:
218 ipv6: will use ping6 command if True; otherwise use ping command
Jon Hall43060f62020-06-23 13:13:33 -0700219 interface: Specify which interface to use for the ping
Pier6a0c4de2018-03-18 16:01:30 -0700220 wait: timeout for ping command
221 """
222 try:
223 command = "ping6" if ipv6 else "ping"
Jon Hall43060f62020-06-23 13:13:33 -0700224 if interface:
225 command += " -I %s " % interface
Pier6a0c4de2018-03-18 16:01:30 -0700226 command += " -c 1 -i 1 -W " + str( wait ) + " " + str( dst )
227 main.log.info( self.name + ": Sending: " + command )
228 self.handle.sendline( command )
229 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700230 timeout=wait + 5 )
Pier6a0c4de2018-03-18 16:01:30 -0700231 if i == 1:
232 main.log.error(
233 self.name +
234 ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700235 main.log.error( self.name + ": response: " + str( self.handle.before ) )
Pier6a0c4de2018-03-18 16:01:30 -0700236 self.handle.sendline( "" )
237 self.handle.expect( self.prompt )
238 response = self.handle.before
239 if re.search( ',\s0\%\spacket\sloss', response ):
240 main.log.info( self.name + ": no packets lost, host is reachable" )
241 return main.TRUE
242 else:
243 main.log.warn(
244 self.name +
245 ": PACKET LOST, HOST IS NOT REACHABLE" )
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
You Wang0fc21702018-11-02 17:49:18 -0700255 def pingHostSetAlternative( self, dstIPList, wait=1, IPv6=False ):
256 """
257 Description:
258 Ping a set of destination host.
259 Params:
260 dstIPList is a list of destination ip addresses
261 Returns:
262 main.TRUE if the destination host is reachable
263 main.FALSE otherwise
264 """
265 isReachable = main.TRUE
266 wait = int( wait )
267 cmd = "ping"
268 if IPv6:
269 cmd = cmd + "6"
270 cmd = cmd + " -c 1 -i 1 -W " + str( wait )
271 try:
272 for dstIP in dstIPList:
273 pingCmd = cmd + " " + dstIP
274 self.handle.sendline( pingCmd )
275 i = self.handle.expect( [ self.prompt,
276 pexpect.TIMEOUT ],
277 timeout=wait + 5 )
278 if i == 0:
279 response = self.handle.before
280 if not re.search( ',\s0\%\spacket\sloss', response ):
281 main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
282 isReachable = main.FALSE
283 elif i == 1:
284 main.log.error( self.name + ": timeout when waiting for response" )
285 isReachable = main.FALSE
286 else:
287 main.log.error( self.name + ": unknown response: " + self.handle.before )
288 isReachable = main.FALSE
289 except pexpect.TIMEOUT:
290 main.log.exception( self.name + ": TIMEOUT exception" )
291 self.exitFromCmd( [ self.prompt ] )
292 isReachable = main.FALSE
293 except pexpect.EOF:
294 main.log.error( self.name + ": EOF exception found" )
295 main.log.error( self.name + ": " + self.handle.before )
296 main.cleanAndExit()
297 except Exception:
298 main.log.exception( self.name + ": Uncaught exception!" )
299 main.cleanAndExit()
300 return isReachable
301
Pier6a0c4de2018-03-18 16:01:30 -0700302 def ifconfig( self, wait=3 ):
303 """
304 Run ifconfig command on host and return output
305 """
306 try:
307 command = "ifconfig"
308 main.log.info( self.name + ": Sending: " + command )
309 self.handle.sendline( command )
310 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
Jon Halla604fd42018-05-04 14:27:27 -0700311 timeout=wait + 5 )
Pier6a0c4de2018-03-18 16:01:30 -0700312 if i == 1:
313 main.log.error(
314 self.name +
315 ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700316 main.log.error( self.name + ": response: " + str( self.handle.before ) )
Pier6a0c4de2018-03-18 16:01:30 -0700317 response = self.handle.before
318 return response
319 except pexpect.EOF:
320 main.log.error( self.name + ": EOF exception found" )
321 main.log.error( self.name + ": " + self.handle.before )
322 main.cleanAndExit()
323 except Exception:
You Wang4cc61912018-08-28 10:10:58 -0700324 main.log.exception( self.name + ": uncaught exception!" )
325 main.cleanAndExit()
326
327 def ip( self, options="a", wait=3 ):
328 """
329 Run ip command on host and return output
330 """
331 try:
332 command = "ip {}".format( options )
333 main.log.info( self.name + ": Sending: " + command )
334 self.handle.sendline( command )
335 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
336 timeout=wait + 5 )
337 if i == 1:
338 main.log.error( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700339 main.log.error( self.name + ": response: " + str( self.handle.before ) )
You Wang4cc61912018-08-28 10:10:58 -0700340 response = self.handle.before
341 return response
342 except pexpect.EOF:
343 main.log.error( self.name + ": EOF exception found" )
344 main.log.error( self.name + ": " + self.handle.before )
345 main.cleanAndExit()
346 except Exception:
347 main.log.exception( self.name + ": uncaught exception!" )
348 main.cleanAndExit()
349
Jon Hall43060f62020-06-23 13:13:33 -0700350 def command( self, cmd, wait=3, debug=False):
You Wang4cc61912018-08-28 10:10:58 -0700351 """
352 Run shell command on host and return output
353 Required:
354 cmd: command to run on the host
355 """
356 try:
357 main.log.info( self.name + ": Sending: " + cmd )
358 self.handle.sendline( cmd )
359 i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
360 timeout=wait + 5 )
Jon Hall43060f62020-06-23 13:13:33 -0700361 response = self.handle.before
362 if debug:
363 main.log.debug( response )
You Wang4cc61912018-08-28 10:10:58 -0700364 if i == 1:
365 main.log.error( self.name + ": timeout when waiting for response" )
Jon Hall43060f62020-06-23 13:13:33 -0700366 main.log.error( self.name + ": response: " + str( response ) )
You Wang4cc61912018-08-28 10:10:58 -0700367 return response
368 except pexpect.EOF:
369 main.log.error( self.name + ": EOF exception found" )
370 main.log.error( self.name + ": " + self.handle.before )
371 main.cleanAndExit()
372 except Exception:
373 main.log.exception( self.name + ": uncaught exception!" )
Pier6a0c4de2018-03-18 16:01:30 -0700374 main.cleanAndExit()