blob: 0f3140a103c08dc656d31cf057e1c76ed7eca4cc [file] [log] [blame]
adminbae64d82013-08-01 10:50:15 -07001#!/usr/bin/env python
kelvin8ec71442015-01-15 16:57:00 -08002"""
adminbae64d82013-08-01 10:50:15 -07003Created on 24-Oct-2012
Jeremy Ronquillo4d5f1d02017-10-13 20:23:57 +00004Copyright 2012 Open Networking Foundation (ONF)
kelvin8ec71442015-01-15 16:57:00 -08005
Jeremy Songsterae01bba2016-07-11 15:39:17 -07006Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
7the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
8or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
adminbae64d82013-08-01 10:50:15 -07009
10 TestON is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 2 of the License, or
Jeremy Ronquillo82705492017-10-18 14:19:55 -070013 (at your option) any later version.
adminbae64d82013-08-01 10:50:15 -070014
15 TestON is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
kelvin8ec71442015-01-15 16:57:00 -080021 along with TestON. If not, see <http://www.gnu.org/licenses/>.
kelvin8ec71442015-01-15 16:57:00 -080022"""
adminbae64d82013-08-01 10:50:15 -070023import pexpect
kelvin8ec71442015-01-15 16:57:00 -080024import re
adminbae64d82013-08-01 10:50:15 -070025
26from drivers.component import Component
kelvin8ec71442015-01-15 16:57:00 -080027
28
29class CLI( Component ):
30
31 """
adminbae64d82013-08-01 10:50:15 -070032 This will define common functions for CLI included.
kelvin8ec71442015-01-15 16:57:00 -080033 """
34 def __init__( self ):
Devin Limdc78e202017-06-09 18:30:07 -070035 super( CLI, self ).__init__()
Jon Hallca319892017-06-15 15:25:22 -070036
Jeremy Ronquillo82705492017-10-18 14:19:55 -070037 def checkPrompt( self ):
Devin Limdc78e202017-06-09 18:30:07 -070038 for key in self.options:
Jeremy Ronquillo82705492017-10-18 14:19:55 -070039 if key == "prompt" and self.options[ 'prompt' ] is not None:
40 self.prompt = self.options[ 'prompt' ]
Devin Limdc78e202017-06-09 18:30:07 -070041 break
kelvin8ec71442015-01-15 16:57:00 -080042
43 def connect( self, **connectargs ):
44 """
adminbae64d82013-08-01 10:50:15 -070045 Connection will establish to the remote host using ssh.
46 It will take user_name ,ip_address and password as arguments<br>
kelvin8ec71442015-01-15 16:57:00 -080047 and will return the handle.
48 """
adminbae64d82013-08-01 10:50:15 -070049 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080050 vars( self )[ key ] = connectargs[ key ]
Devin Limdc78e202017-06-09 18:30:07 -070051 self.checkPrompt()
adminbae64d82013-08-01 10:50:15 -070052
kelvin8ec71442015-01-15 16:57:00 -080053 connect_result = super( CLI, self ).connect()
adminbae64d82013-08-01 10:50:15 -070054 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -080055 refused = "ssh: connect to host " + \
56 self.ip_address + " port 22: Connection refused"
adminbae64d82013-08-01 10:50:15 -070057 if self.port:
kelvin8ec71442015-01-15 16:57:00 -080058 self.handle = pexpect.spawn(
59 'ssh -p ' +
60 self.port +
61 ' ' +
62 self.user_name +
63 '@' +
64 self.ip_address,
Jon Hall9aaba882015-01-19 15:05:15 -080065 env={ "TERM": "xterm-mono" },
kelvin8ec71442015-01-15 16:57:00 -080066 maxread=50000 )
67 else:
68 self.handle = pexpect.spawn(
69 'ssh -X ' +
70 self.user_name +
71 '@' +
72 self.ip_address,
Jon Hall9aaba882015-01-19 15:05:15 -080073 env={ "TERM": "xterm-mono" },
kelvin8ec71442015-01-15 16:57:00 -080074 maxread=1000000,
75 timeout=60 )
adminbae64d82013-08-01 10:50:15 -070076
Jon Hall73057ee2016-08-23 09:57:26 -070077 # set tty window size
78 self.handle.setwinsize( 24, 250 )
79
adminbae64d82013-08-01 10:50:15 -070080 self.handle.logfile = self.logfile_handler
kelvin8ec71442015-01-15 16:57:00 -080081 i = 5
82 while i == 5:
Jon Hall4173b242017-09-12 17:04:38 -070083 i = self.handle.expect( [ ssh_newkey,
84 'password:|Password:',
85 pexpect.EOF,
86 pexpect.TIMEOUT,
87 refused,
88 'teston>',
89 self.prompt ],
90 120 )
acsmars32de0bc2015-06-30 09:57:12 -070091 if i == 0: # Accept key, then expect either a password prompt or access
kelvin8ec71442015-01-15 16:57:00 -080092 main.log.info( "ssh key confirmation received, send yes" )
93 self.handle.sendline( 'yes' )
acsmars32de0bc2015-06-30 09:57:12 -070094 i = 5 # Run the loop again
acsmars07f9d392015-07-15 10:30:58 -070095 continue
96 if i == 1: # Password required
Jon Hall63604932015-02-26 17:09:50 -080097 if self.pwd:
98 main.log.info(
Jon Hall4173b242017-09-12 17:04:38 -070099 "ssh connection asked for password, gave password" )
Jon Hall63604932015-02-26 17:09:50 -0800100 else:
acsmars07f9d392015-07-15 10:30:58 -0700101 main.log.info( "Server asked for password, but none was "
102 "given in the .topo file. Trying "
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700103 "no password." )
acsmars07f9d392015-07-15 10:30:58 -0700104 self.pwd = ""
105 self.handle.sendline( self.pwd )
106 j = self.handle.expect( [
Devin Limdc78e202017-06-09 18:30:07 -0700107 self.prompt,
acsmars07f9d392015-07-15 10:30:58 -0700108 'password:|Password:',
109 pexpect.EOF,
110 pexpect.TIMEOUT ],
111 120 )
112 if j != 0:
113 main.log.error( "Incorrect Password" )
114 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -0800115 elif i == 2:
116 main.log.error( "Connection timeout" )
117 return main.FALSE
118 elif i == 3: # timeout
119 main.log.error(
120 "No route to the Host " +
121 self.user_name +
122 "@" +
123 self.ip_address )
124 return main.FALSE
125 elif i == 4:
126 main.log.error(
127 "ssh: connect to host " +
128 self.ip_address +
129 " port 22: Connection refused" )
130 return main.FALSE
131 elif i == 6:
132 main.log.info( "Password not required logged in" )
adminbae64d82013-08-01 10:50:15 -0700133
kelvin8ec71442015-01-15 16:57:00 -0800134 self.handle.sendline( "" )
Devin Limdc78e202017-06-09 18:30:07 -0700135 self.handle.expect( self.prompt )
Jeremy Ronquillo0f2008a2017-06-23 15:32:51 -0700136 self.handle.sendline( "cd" )
137 self.handle.expect( self.prompt )
adminbae64d82013-08-01 10:50:15 -0700138 return self.handle
139
kelvin8ec71442015-01-15 16:57:00 -0800140 def disconnect( self ):
141 result = super( CLI, self ).disconnect( self )
adminbae64d82013-08-01 10:50:15 -0700142 result = main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800143 # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
144
145 def execute( self, **execparams ):
146 """
adminbae64d82013-08-01 10:50:15 -0700147 It facilitates the command line execution of a given command. It has arguments as :
148 cmd => represents command to be executed,
149 prompt => represents expect command prompt or output,
150 timeout => timeout for command execution,
151 more => to provide a key press if it is on.
152
153 It will return output of command exection.
kelvin8ec71442015-01-15 16:57:00 -0800154 """
155 result = super( CLI, self ).execute( self )
adminaef00552014-05-08 09:18:36 -0700156 defaultPrompt = '.*[$>\#]'
Jon Hall3b489db2015-10-05 14:38:37 -0700157 args = utilities.parse_args( [ "CMD",
158 "TIMEOUT",
159 "PROMPT",
160 "MORE" ],
161 **execparams )
kelvin8ec71442015-01-15 16:57:00 -0800162
163 expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
adminbae64d82013-08-01 10:50:15 -0700164 self.LASTRSP = ""
kelvin8ec71442015-01-15 16:57:00 -0800165 timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
adminbae64d82013-08-01 10:50:15 -0700166 cmd = ''
kelvin8ec71442015-01-15 16:57:00 -0800167 if args[ "CMD" ]:
168 cmd = args[ "CMD" ]
169 else:
adminbae64d82013-08-01 10:50:15 -0700170 return 0
kelvin8ec71442015-01-15 16:57:00 -0800171 if args[ "MORE" ] is None:
172 args[ "MORE" ] = " "
173 self.handle.sendline( cmd )
adminbae64d82013-08-01 10:50:15 -0700174 self.lastCommand = cmd
Jon Hall3b489db2015-10-05 14:38:37 -0700175 index = self.handle.expect( [ expectPrompt,
176 "--More--",
177 'Command not found.',
178 pexpect.TIMEOUT,
179 "^:$" ],
180 timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700181 if index == 0:
kelvin8ec71442015-01-15 16:57:00 -0800182 self.LASTRSP = self.LASTRSP + \
183 self.handle.before + self.handle.after
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700184 main.log.info( "Executed :" + str( cmd ) +
185 " \t\t Expected Prompt '" + str( expectPrompt ) +
Jon Hall3b489db2015-10-05 14:38:37 -0700186 "' Found" )
adminbae64d82013-08-01 10:50:15 -0700187 elif index == 1:
188 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800189 self.handle.send( args[ "MORE" ] )
190 main.log.info(
191 "Found More screen to go , Sending a key to proceed" )
192 indexMore = self.handle.expect(
193 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700194 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800195 main.log.info(
196 "Found anoother More screen to go , Sending a key to proceed" )
197 self.handle.send( args[ "MORE" ] )
198 indexMore = self.handle.expect(
199 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700200 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800201 elif index == 2:
202 main.log.error( "Command not found" )
adminbae64d82013-08-01 10:50:15 -0700203 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800204 elif index == 3:
Jon Hall3b489db2015-10-05 14:38:37 -0700205 main.log.error( "Expected Prompt not found, Time Out!!" )
kelvin8ec71442015-01-15 16:57:00 -0800206 main.log.error( expectPrompt )
Jon Hall3b489db2015-10-05 14:38:37 -0700207 self.LASTRSP = self.LASTRSP + self.handle.before
208 return self.LASTRSP
adminbae64d82013-08-01 10:50:15 -0700209 elif index == 4:
210 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800211 # self.handle.send( args[ "MORE" ] )
212 self.handle.sendcontrol( "D" )
213 main.log.info(
Jon Hall3b489db2015-10-05 14:38:37 -0700214 "Found More screen to go, Sending a key to proceed" )
kelvin8ec71442015-01-15 16:57:00 -0800215 indexMore = self.handle.expect(
216 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700217 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800218 main.log.info(
Jon Hall3b489db2015-10-05 14:38:37 -0700219 "Found another More screen to go, Sending a key to proceed" )
kelvin8ec71442015-01-15 16:57:00 -0800220 self.handle.sendcontrol( "D" )
221 indexMore = self.handle.expect(
222 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700223 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800224 main.last_response = self.remove_contol_chars( self.LASTRSP )
adminbae64d82013-08-01 10:50:15 -0700225 return self.LASTRSP
kelvin8ec71442015-01-15 16:57:00 -0800226
227 def remove_contol_chars( self, response ):
228 # RE_XML_ILLEGAL = '([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])|([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])'%( unichr( 0xd800 ),unichr( 0xdbff ),unichr( 0xdc00 ),unichr( 0xdfff ),unichr( 0xd800 ),unichr( 0xdbff ),unichr( 0xdc00 ),unichr( 0xdfff ),unichr( 0xd800 ),unichr( 0xdbff ),unichr( 0xdc00 ),unichr( 0xdfff ) )
229 # response = re.sub( RE_XML_ILLEGAL, "\n", response )
230 response = re.sub( r"[\x01-\x1F\x7F]", "", response )
231 # response = re.sub( r"\[\d+\;1H", "\n", response )
232 response = re.sub( r"\[\d+\;\d+H", "", response )
adminbae64d82013-08-01 10:50:15 -0700233 return response
adminbae64d82013-08-01 10:50:15 -0700234
kelvin8ec71442015-01-15 16:57:00 -0800235 def runAsSudoUser( self, handle, pwd, default ):
236
237 i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
238 if i == 0:
239 handle.sendline( pwd )
Jon Hall5ec6b1b2015-09-17 18:20:14 -0700240 handle.sendline( "\n" )
kelvin8ec71442015-01-15 16:57:00 -0800241
242 if i == 1:
243 handle.expect( default )
244
245 if i == 2:
246 main.log.error( "Unable to run as Sudo user" )
247
adminbae64d82013-08-01 10:50:15 -0700248 return handle
adminbae64d82013-08-01 10:50:15 -0700249
kelvin8ec71442015-01-15 16:57:00 -0800250 def onfail( self ):
251 if 'onfail' in main.componentDictionary[ self.name ]:
252 commandList = main.componentDictionary[
253 self.name ][ 'onfail' ].split( "," )
254 for command in commandList:
255 response = self.execute(
256 cmd=command,
257 prompt="(.*)",
258 timeout=120 )
adminbae64d82013-08-01 10:50:15 -0700259
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700260 def secureCopy( self, userName, ipAddress, filePath, dstPath, pwd="",
261 direction="from" ):
kelvin8ec71442015-01-15 16:57:00 -0800262 """
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700263 Definition:
264 Execute scp command in linux to copy to/from a remote host
265 Required:
266 str userName - User name of the remote host
267 str ipAddress - IP address of the remote host
268 str filePath - File path including the file it self
269 str dstPath - Destination path
270 Optional:
271 str pwd - Password of the host
272 str direction - Direction of the scp, default to "from" which means
273 copy "from" the remote machine to local machine,
274 while "to" means copy "to" the remote machine from
275 local machine
kelvin8ec71442015-01-15 16:57:00 -0800276 """
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700277 returnVal = main.TRUE
adminbae64d82013-08-01 10:50:15 -0700278 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -0800279 refused = "ssh: connect to host " + \
Jon Hall547e0582015-09-21 17:35:40 -0700280 ipAddress + " port 22: Connection refused"
acsmars07f9d392015-07-15 10:30:58 -0700281
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700282 if direction == "from":
283 cmd = 'scp ' + str( userName ) + '@' + str( ipAddress ) + ':' + \
Jon Hall547e0582015-09-21 17:35:40 -0700284 str( filePath ) + ' ' + str( dstPath )
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700285 elif direction == "to":
286 cmd = 'scp ' + str( filePath ) + ' ' + str( userName ) + \
Jon Hall547e0582015-09-21 17:35:40 -0700287 '@' + str( ipAddress ) + ':' + str( dstPath )
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700288 else:
289 main.log.debug( "Wrong direction using secure copy command!" )
290 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -0800291
292 main.log.info( "Sending: " + cmd )
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700293 self.handle.sendline( cmd )
Jon Hall547e0582015-09-21 17:35:40 -0700294 i = 0
295 while i < 2:
296 i = self.handle.expect( [
297 ssh_newkey,
298 'password:',
299 "100%",
300 refused,
301 "No such file or directory",
Jon Hall53c5e662016-04-13 16:06:56 -0700302 "Permission denied",
Devin Limdc78e202017-06-09 18:30:07 -0700303 self.prompt,
Jon Hall547e0582015-09-21 17:35:40 -0700304 pexpect.EOF,
305 pexpect.TIMEOUT ],
306 120 )
Jon Hall547e0582015-09-21 17:35:40 -0700307 if i == 0: # ask for ssh key confirmation
308 main.log.info( "ssh key confirmation received, sending yes" )
309 self.handle.sendline( 'yes' )
310 elif i == 1: # Asked for ssh password
311 main.log.info( "ssh connection asked for password, gave password" )
312 self.handle.sendline( pwd )
313 elif i == 2: # File finished transfering
314 main.log.info( "Secure copy successful" )
315 returnVal = main.TRUE
316 elif i == 3: # Connection refused
317 main.log.error(
318 "ssh: connect to host " +
319 ipAddress +
320 " port 22: Connection refused" )
321 returnVal = main.FALSE
322 elif i == 4: # File Not found
323 main.log.error( "No such file found" )
324 returnVal = main.FALSE
Jon Hall53c5e662016-04-13 16:06:56 -0700325 elif i == 5: # Permission denied
326 main.log.error( "Permission denied. Check folder permissions" )
327 returnVal = main.FALSE
328 elif i == 6: # prompt returned
Jon Hall4173b242017-09-12 17:04:38 -0700329 return returnVal
Jon Hall53c5e662016-04-13 16:06:56 -0700330 elif i == 7: # EOF
Jon Hall547e0582015-09-21 17:35:40 -0700331 main.log.error( "Pexpect.EOF found!!!" )
Devin Lim44075962017-08-11 10:56:37 -0700332 main.cleanAndExit()
Jon Hall53c5e662016-04-13 16:06:56 -0700333 elif i == 8: # timeout
Jon Hall547e0582015-09-21 17:35:40 -0700334 main.log.error(
335 "No route to the Host " +
336 userName +
337 "@" +
338 ipAddress )
339 returnVal = main.FALSE
Devin Limdc78e202017-06-09 18:30:07 -0700340 self.handle.expect( self.prompt )
kelvin-onlabd9e23de2015-08-06 10:34:44 -0700341 return returnVal
342
343 def scp( self, remoteHost, filePath, dstPath, direction="from" ):
344 """
345 Definition:
346 Execute scp command in linux to copy to/from a remote host
347 Required:
348 * remoteHost - Test ON component to be parsed
349 str filePath - File path including the file it self
350 str dstPath - Destination path
351 Optional:
352 str direction - Direction of the scp, default to "from" which means
353 copy "from" the remote machine to local machine,
354 while "to" means copy "to" the remote machine from
355 local machine
356 """
357 return self.secureCopy( remoteHost.user_name,
358 remoteHost.ip_address,
359 filePath,
360 dstPath,
361 pwd=remoteHost.pwd,
362 direction=direction )
Devin Lim142b5342017-07-20 15:22:39 -0700363
364 def sshToNode( self, ipAddress, uName="sdn", pwd="rocks" ):
365 ssh_newkey = 'Are you sure you want to continue connecting'
366 refused = "ssh: connect to host " + ipAddress + " port 22: Connection refused"
367 handle = pexpect.spawn( 'ssh -X ' +
368 uName +
369 '@' +
370 ipAddress,
371 env={ "TERM": "xterm-mono" },
372 maxread=1000000,
373 timeout=60 )
374
375 # set tty window size
376 handle.setwinsize( 24, 250 )
377
378 i = 5
379 while i == 5:
Jon Hall4173b242017-09-12 17:04:38 -0700380 i = handle.expect( [ ssh_newkey,
381 'password:|Password:',
382 pexpect.EOF,
383 pexpect.TIMEOUT,
384 refused,
385 'teston>',
386 self.prompt ],
387 120 )
Devin Lim142b5342017-07-20 15:22:39 -0700388 if i == 0: # Accept key, then expect either a password prompt or access
389 main.log.info( "ssh key confirmation received, send yes" )
390 handle.sendline( 'yes' )
391 i = 5 # Run the loop again
392 continue
393 if i == 1: # Password required
394 if pwd:
395 main.log.info(
Jon Hall4173b242017-09-12 17:04:38 -0700396 "ssh connection asked for password, gave password" )
Devin Lim142b5342017-07-20 15:22:39 -0700397 else:
398 main.log.info( "Server asked for password, but none was "
399 "given in the .topo file. Trying "
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700400 "no password." )
Devin Lim142b5342017-07-20 15:22:39 -0700401 pwd = ""
402 handle.sendline( pwd )
403 j = handle.expect( [ self.prompt,
404 'password:|Password:',
405 pexpect.EOF,
406 pexpect.TIMEOUT ],
407 120 )
408 if j != 0:
409 main.log.error( "Incorrect Password" )
Devin Lim44075962017-08-11 10:56:37 -0700410 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -0700411 elif i == 2:
412 main.log.error( "Connection timeout" )
Devin Lim44075962017-08-11 10:56:37 -0700413 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -0700414 elif i == 3: # timeout
415 main.log.error(
416 "No route to the Host " +
417 uName +
418 "@" +
419 ipAddress )
Devin Lim44075962017-08-11 10:56:37 -0700420 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -0700421 elif i == 4:
422 main.log.error(
423 "ssh: connect to host " +
424 ipAddress +
425 " port 22: Connection refused" )
Devin Lim44075962017-08-11 10:56:37 -0700426 main.cleanAndExit()
Devin Lim142b5342017-07-20 15:22:39 -0700427 elif i == 6:
428 main.log.info( "Password not required logged in" )
429
430 handle.sendline( "" )
431 handle.expect( self.prompt )
432 handle.sendline( "cd" )
433 handle.expect( self.prompt )
434
Jon Hall4173b242017-09-12 17:04:38 -0700435 main.log.info( "Successfully ssh to " + ipAddress + "." )
Devin Lim142b5342017-07-20 15:22:39 -0700436 return handle
437
438 def exitFromSsh( self, handle, ipAddress ):
Devin Lim142b5342017-07-20 15:22:39 -0700439 try:
Jon Hall4f360bc2017-09-07 10:19:52 -0700440 handle.sendline( "logout" )
Devin Lim142b5342017-07-20 15:22:39 -0700441 handle.expect( "closed." )
Jon Hall4173b242017-09-12 17:04:38 -0700442 main.log.info( "Successfully closed ssh connection from " + ipAddress )
Devin Lim142b5342017-07-20 15:22:39 -0700443 except pexpect.EOF:
444 main.log.error( "Failed to close the connection from " + ipAddress )
Jon Hall4f360bc2017-09-07 10:19:52 -0700445 try:
446 # check that this component handle still works
447 self.handle.sendline( "" )
448 self.handle.expect( self.prompt )
449 except pexpect.EOF:
450 main.log.error( self.handle.before )
451 main.log.error( "EOF after closing ssh connection" )
Jon Hall4173b242017-09-12 17:04:38 -0700452
453 def folderSize( self, path, size='10', unit='M', ignoreRoot=True ):
454 """
455 Run `du -h` on the folder path and verifies the folder(s) size is
456 less than the given size. Note that if multiple subdirectories are
457 present, the result will be the OR of all the individual subdirectories.
458
459 Arguments:
460 path - A string containing the path supplied to the du command
461 size - The number portion of the file size that the results will be compared to
462 unit - The unit portion of the file size that the results will be compared to
463 ignoreRoot - If True, will ignore the "root" of the path supplied to du. I.E. will ignore `.`
464
465 Returns True if the folder(s) size(s) are less than SIZE UNITS, else returns False
466 """
467 sizeRe = r'(?P<number>\d+\.*\d*)(?P<unit>\D)'
468 unitsList = [ 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ]
469 try:
470 # make sure we convert units if size is too big
471 size = float( size )
472 if size >= 1000:
473 size = size / 1000
474 unit = unitsList[ unitsList.index( unit + 1 ) ]
475 cmdStr = "du -h " + path
476 self.handle.sendline( cmdStr )
477 self.handle.expect( self.prompt )
478 output = self.handle.before
479 assert "cannot access" not in output
480 assert "command not found" not in output
481 main.log.debug( output )
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700482 lines = [ line for line in output.split( '\r\n' ) ]
Jon Hall4173b242017-09-12 17:04:38 -0700483 retValue = True
484 if ignoreRoot:
485 lastIndex = -2
486 else:
487 lastIndex = -1
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700488 for line in lines[ 1:lastIndex ]:
Jon Hall4173b242017-09-12 17:04:38 -0700489 parsed = line.split()
Jeremy Ronquillo82705492017-10-18 14:19:55 -0700490 sizeMatch = parsed[ 0 ]
491 folder = parsed[ 1 ]
Jon Hall4173b242017-09-12 17:04:38 -0700492 match = re.search( sizeRe, sizeMatch )
493 num = match.group( 'number' )
494 unitMatch = match.group( 'unit' )
495 if unitsList.index( unitMatch ) < unitsList.index( unit ):
496 retValue &= True
497 elif unitsList.index( unitMatch ) == unitsList.index( unit ):
498 if float( num ) < float( size ):
499 retValue &= True
500 else:
501 retValue &= False
502 elif unitsList.index( unitMatch ) > unitsList.index( unit ):
503 retValue &= False
504 return retValue
505 except AssertionError:
506 main.log.error( self.name + ": Could not execute command: " + output )
507 return False
508 except pexpect.TIMEOUT:
509 main.log.exception( self.name + ": TIMEOUT exception found" )
510 main.log.error( self.name + ": " + self.handle.before )
511 return False
512 except pexpect.EOF:
513 main.log.error( self.name + ": EOF exception found" )
514 main.log.error( self.name + ": " + self.handle.before )
515 main.cleanAndExit()