blob: ce10a2c4bb813a7b1fc47bd7772bc6680526ba37 [file] [log] [blame]
Chetan Gaonker3ff8eae2016-04-12 14:50:26 -07001#!/usr/bin/env python
2"""
3Created on 24-Oct-2012
4
5author:s: Anil Kumar ( anilkumar.s@paxterrasolutions.com ),
6 Raghav Kashyap( raghavkashyap@paxterrasolutions.com )
7
8
9 TestON is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 2 of the License, or
12 ( at your option ) any later version.
13
14 TestON is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with TestON. If not, see <http://www.gnu.org/licenses/>.
21
22
23
24"""
25import pexpect
26import re
27from component import Component
28from clicommon import *
29import os
30
31class CLI( Component ):
32
33 """
34 This will define common functions for CLI included.
35 """
36 def __init__( self ):
37 super( Component, self ).__init__()
38
39 def connect( self, **connectargs ):
40 """
41 Connection will establish to the remote host using ssh.
42 It will take user_name ,ip_address and password as arguments<br>
43 and will return the handle.
44 """
45 for key in connectargs:
46 vars( self )[ key ] = connectargs[ key ]
47
48 connect_result = super( CLI, self ).connect()
49 ssh_newkey = 'Are you sure you want to continue connecting'
50 refused = "ssh: connect to host " + \
51 self.ip_address + " port 22: Connection refused"
52 if self.port:
53 ssh_hosts_file = os.path.join(os.getenv('HOME'), '.ssh', 'known_hosts')
54 cmd_host_remove = 'ssh-keygen -f "%s" -R [%s]:8101' %(ssh_hosts_file, self.ip_address)
55 #os.system(cmd_host_remove)
56 #main.log.info('SSH host remove cmd: %s' %cmd_host_remove)
57 main.log.info('Spawning pexpect for ip %s' %self.ip_address)
58 self.handle = pexpect.spawn(
59 'ssh -p ' +
60 self.port +
61 ' ' +
62 '-o StrictHostKeyChecking=no ' +
63 self.user_name +
64 '@' +
65 self.ip_address,
66 env={ "TERM": "xterm-mono" },
67 maxread=50000 )
68 else:
69 self.handle = pexpect.spawn(
70 'ssh -X ' +
71 self.user_name +
72 '@' +
73 self.ip_address,
74 env={ "TERM": "xterm-mono" },
75 maxread=1000000,
76 timeout=60 )
77
78 self.handle.logfile = self.logfile_handler
79 i = 5
80 while i == 5:
81 i = self.handle.expect( [
82 ssh_newkey,
83 'password:|Password:',
84 pexpect.EOF,
85 pexpect.TIMEOUT,
86 refused,
87 'teston>',
88 '>|#|\$' ],
89 120 )
90 if i == 0: # Accept key, then expect either a password prompt or access
91 main.log.info( "ssh key confirmation received, send yes" )
92 self.handle.sendline( 'yes' )
93 i = 5 # Run the loop again
94 continue
95 if i == 1: # Password required
96 if self.pwd:
97 main.log.info(
98 "ssh connection asked for password, gave password" )
99 else:
100 main.log.info( "Server asked for password, but none was "
101 "given in the .topo file. Trying "
102 "no password.")
103 self.pwd = ""
104 self.handle.sendline( self.pwd )
105 j = self.handle.expect( [
106 '>|#|\$',
107 'password:|Password:',
108 pexpect.EOF,
109 pexpect.TIMEOUT ],
110 120 )
111 if j != 0:
112 main.log.error( "Incorrect Password" )
113 return main.FALSE
114 elif i == 2:
115 main.log.error( "Connection timeout" )
116 return main.FALSE
117 elif i == 3: # timeout
118 main.log.error(
119 "No route to the Host " +
120 self.user_name +
121 "@" +
122 self.ip_address )
123 return main.FALSE
124 elif i == 4:
125 main.log.error(
126 "ssh: connect to host " +
127 self.ip_address +
128 " port 22: Connection refused" )
129 return main.FALSE
130 elif i == 6:
131 main.log.info( "Password not required logged in" )
132
133 self.handle.sendline( "" )
134 self.handle.expect( '>|#|\$' )
135 return self.handle
136
137 def disconnect( self ):
138 result = super( CLI, self ).disconnect( self )
139 result = main.TRUE
140 # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
141
142 def execute( self, **execparams ):
143 """
144 It facilitates the command line execution of a given command. It has arguments as :
145 cmd => represents command to be executed,
146 prompt => represents expect command prompt or output,
147 timeout => timeout for command execution,
148 more => to provide a key press if it is on.
149
150 It will return output of command exection.
151 """
152 result = super( CLI, self ).execute( self )
153 defaultPrompt = '.*[$>\#]'
154 args = utilities.parse_args( [ "CMD",
155 "TIMEOUT",
156 "PROMPT",
157 "MORE" ],
158 **execparams )
159
160 expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
161 self.LASTRSP = ""
162 timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
163 cmd = ''
164 if args[ "CMD" ]:
165 cmd = args[ "CMD" ]
166 else:
167 return 0
168 if args[ "MORE" ] is None:
169 args[ "MORE" ] = " "
170 self.handle.sendline( cmd )
171 self.lastCommand = cmd
172 index = self.handle.expect( [ expectPrompt,
173 "--More--",
174 'Command not found.',
175 pexpect.TIMEOUT,
176 "^:$" ],
177 timeout=timeoutVar )
178 if index == 0:
179 self.LASTRSP = self.LASTRSP + \
180 self.handle.before + self.handle.after
181 main.log.info( "Executed :" + str(cmd ) +
182 " \t\t Expected Prompt '" + str( expectPrompt) +
183 "' Found" )
184 elif index == 1:
185 self.LASTRSP = self.LASTRSP + self.handle.before
186 self.handle.send( args[ "MORE" ] )
187 main.log.info(
188 "Found More screen to go , Sending a key to proceed" )
189 indexMore = self.handle.expect(
190 [ "--More--", expectPrompt ], timeout=timeoutVar )
191 while indexMore == 0:
192 main.log.info(
193 "Found anoother More screen to go , Sending a key to proceed" )
194 self.handle.send( args[ "MORE" ] )
195 indexMore = self.handle.expect(
196 [ "--More--", expectPrompt ], timeout=timeoutVar )
197 self.LASTRSP = self.LASTRSP + self.handle.before
198 elif index == 2:
199 main.log.error( "Command not found" )
200 self.LASTRSP = self.LASTRSP + self.handle.before
201 elif index == 3:
202 main.log.error( "Expected Prompt not found, Time Out!!" )
203 main.log.error( expectPrompt )
204 self.LASTRSP = self.LASTRSP + self.handle.before
205 return self.LASTRSP
206 elif index == 4:
207 self.LASTRSP = self.LASTRSP + self.handle.before
208 # self.handle.send( args[ "MORE" ] )
209 self.handle.sendcontrol( "D" )
210 main.log.info(
211 "Found More screen to go, Sending a key to proceed" )
212 indexMore = self.handle.expect(
213 [ "^:$", expectPrompt ], timeout=timeoutVar )
214 while indexMore == 0:
215 main.log.info(
216 "Found another More screen to go, Sending a key to proceed" )
217 self.handle.sendcontrol( "D" )
218 indexMore = self.handle.expect(
219 [ "^:$", expectPrompt ], timeout=timeoutVar )
220 self.LASTRSP = self.LASTRSP + self.handle.before
221 main.last_response = self.remove_contol_chars( self.LASTRSP )
222 return self.LASTRSP
223
224 def remove_contol_chars( self, response ):
225 # 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 ) )
226 # response = re.sub( RE_XML_ILLEGAL, "\n", response )
227 response = re.sub( r"[\x01-\x1F\x7F]", "", response )
228 # response = re.sub( r"\[\d+\;1H", "\n", response )
229 response = re.sub( r"\[\d+\;\d+H", "", response )
230 return response
231
232 def runAsSudoUser( self, handle, pwd, default ):
233
234 i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
235 if i == 0:
236 handle.sendline( pwd )
237 handle.sendline( "\n" )
238
239 if i == 1:
240 handle.expect( default )
241
242 if i == 2:
243 main.log.error( "Unable to run as Sudo user" )
244
245 return handle
246
247 def onfail( self ):
248 if 'onfail' in main.componentDictionary[ self.name ]:
249 commandList = main.componentDictionary[
250 self.name ][ 'onfail' ].split( "," )
251 for command in commandList:
252 response = self.execute(
253 cmd=command,
254 prompt="(.*)",
255 timeout=120 )
256
257 def secureCopy( self, userName, ipAddress, filePath, dstPath, pwd="",
258 direction="from" ):
259 """
260 Definition:
261 Execute scp command in linux to copy to/from a remote host
262 Required:
263 str userName - User name of the remote host
264 str ipAddress - IP address of the remote host
265 str filePath - File path including the file it self
266 str dstPath - Destination path
267 Optional:
268 str pwd - Password of the host
269 str direction - Direction of the scp, default to "from" which means
270 copy "from" the remote machine to local machine,
271 while "to" means copy "to" the remote machine from
272 local machine
273 """
274 returnVal = main.TRUE
275 ssh_newkey = 'Are you sure you want to continue connecting'
276 refused = "ssh: connect to host " + \
277 ipAddress + " port 22: Connection refused"
278
279 if direction == "from":
280 cmd = 'scp ' + str( userName ) + '@' + str( ipAddress ) + ':' + \
281 str( filePath ) + ' ' + str( dstPath )
282 elif direction == "to":
283 cmd = 'scp ' + str( filePath ) + ' ' + str( userName ) + \
284 '@' + str( ipAddress ) + ':' + str( dstPath )
285 else:
286 main.log.debug( "Wrong direction using secure copy command!" )
287 return main.FALSE
288
289 main.log.info( "Sending: " + cmd )
290 self.handle.sendline( cmd )
291 i = 0
292 while i < 2:
293 i = self.handle.expect( [
294 ssh_newkey,
295 'password:',
296 "100%",
297 refused,
298 "No such file or directory",
299 pexpect.EOF,
300 pexpect.TIMEOUT ],
301 120 )
302 if i == 0: # ask for ssh key confirmation
303 main.log.info( "ssh key confirmation received, sending yes" )
304 self.handle.sendline( 'yes' )
305 elif i == 1: # Asked for ssh password
306 main.log.info( "ssh connection asked for password, gave password" )
307 self.handle.sendline( pwd )
308 elif i == 2: # File finished transfering
309 main.log.info( "Secure copy successful" )
310 returnVal = main.TRUE
311 elif i == 3: # Connection refused
312 main.log.error(
313 "ssh: connect to host " +
314 ipAddress +
315 " port 22: Connection refused" )
316 returnVal = main.FALSE
317 elif i == 4: # File Not found
318 main.log.error( "No such file found" )
319 returnVal = main.FALSE
320 elif i == 5: # EOF
321 main.log.error( "Pexpect.EOF found!!!" )
322 main.cleanup()
323 main.exit()
324 elif i == 6: # timeout
325 main.log.error(
326 "No route to the Host " +
327 userName +
328 "@" +
329 ipAddress )
330 returnVal = main.FALSE
331 self.handle.expect( "\$" )
332 return returnVal
333
334 def scp( self, remoteHost, filePath, dstPath, direction="from" ):
335 """
336 Definition:
337 Execute scp command in linux to copy to/from a remote host
338 Required:
339 * remoteHost - Test ON component to be parsed
340 str filePath - File path including the file it self
341 str dstPath - Destination path
342 Optional:
343 str direction - Direction of the scp, default to "from" which means
344 copy "from" the remote machine to local machine,
345 while "to" means copy "to" the remote machine from
346 local machine
347 """
348 return self.secureCopy( remoteHost.user_name,
349 remoteHost.ip_address,
350 filePath,
351 dstPath,
352 pwd=remoteHost.pwd,
353 direction=direction )