blob: b4d0251e999197432a22a487836ff2e7709d3932 [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
kelvin8ec71442015-01-15 16:57:00 -08004
5author:s: Anil Kumar ( anilkumar.s@paxterrasolutions.com ),
6 Raghav Kashyap( raghavkashyap@paxterrasolutions.com )
adminbae64d82013-08-01 10:50:15 -07007
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
kelvin8ec71442015-01-15 16:57:00 -080012 ( at your option ) any later version.
adminbae64d82013-08-01 10:50:15 -070013
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
kelvin8ec71442015-01-15 16:57:00 -080020 along with TestON. If not, see <http://www.gnu.org/licenses/>.
adminbae64d82013-08-01 10:50:15 -070021
22
kelvin8ec71442015-01-15 16:57:00 -080023
24"""
adminbae64d82013-08-01 10:50:15 -070025import pexpect
kelvin8ec71442015-01-15 16:57:00 -080026import struct
27import fcntl
28import os
29import sys
30import signal
31import sys
32import re
33sys.path.append( "../" )
adminbae64d82013-08-01 10:50:15 -070034
35from drivers.component import Component
kelvin8ec71442015-01-15 16:57:00 -080036
37
38class CLI( Component ):
39
40 """
adminbae64d82013-08-01 10:50:15 -070041 This will define common functions for CLI included.
kelvin8ec71442015-01-15 16:57:00 -080042 """
43 def __init__( self ):
44 super( Component, self ).__init__()
45
46 def connect( self, **connectargs ):
47 """
adminbae64d82013-08-01 10:50:15 -070048 Connection will establish to the remote host using ssh.
49 It will take user_name ,ip_address and password as arguments<br>
kelvin8ec71442015-01-15 16:57:00 -080050 and will return the handle.
51 """
adminbae64d82013-08-01 10:50:15 -070052 for key in connectargs:
kelvin8ec71442015-01-15 16:57:00 -080053 vars( self )[ key ] = connectargs[ key ]
adminbae64d82013-08-01 10:50:15 -070054
kelvin8ec71442015-01-15 16:57:00 -080055 connect_result = super( CLI, self ).connect()
adminbae64d82013-08-01 10:50:15 -070056 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -080057 refused = "ssh: connect to host " + \
58 self.ip_address + " port 22: Connection refused"
adminbae64d82013-08-01 10:50:15 -070059 if self.port:
kelvin8ec71442015-01-15 16:57:00 -080060 self.handle = pexpect.spawn(
61 'ssh -p ' +
62 self.port +
63 ' ' +
64 self.user_name +
65 '@' +
66 self.ip_address,
Jon Hall9aaba882015-01-19 15:05:15 -080067 env={ "TERM": "xterm-mono" },
kelvin8ec71442015-01-15 16:57:00 -080068 maxread=50000 )
69 else:
70 self.handle = pexpect.spawn(
71 'ssh -X ' +
72 self.user_name +
73 '@' +
74 self.ip_address,
Jon Hall9aaba882015-01-19 15:05:15 -080075 env={ "TERM": "xterm-mono" },
kelvin8ec71442015-01-15 16:57:00 -080076 maxread=1000000,
77 timeout=60 )
adminbae64d82013-08-01 10:50:15 -070078
79 self.handle.logfile = self.logfile_handler
kelvin8ec71442015-01-15 16:57:00 -080080 i = 5
81 while i == 5:
82 i = self.handle.expect( [
acsmarse2be32c2015-06-29 16:16:28 -070083 ssh_newkey,
Jon Hall05f88682015-06-09 14:57:53 -070084 'password:|Password:',
kelvin8ec71442015-01-15 16:57:00 -080085 pexpect.EOF,
86 pexpect.TIMEOUT,
87 refused,
88 'teston>',
89 '>|#|\$' ],
acsmars07f9d392015-07-15 10:30:58 -070090 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(
acsmars07f9d392015-07-15 10:30:58 -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 "
103 "no password.")
104 self.pwd = ""
105 self.handle.sendline( self.pwd )
106 j = self.handle.expect( [
107 '>|#|\$',
108 '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( "" )
135 self.handle.expect( '>|#|\$' )
adminbae64d82013-08-01 10:50:15 -0700136 return self.handle
137
kelvin8ec71442015-01-15 16:57:00 -0800138 def disconnect( self ):
139 result = super( CLI, self ).disconnect( self )
adminbae64d82013-08-01 10:50:15 -0700140 result = main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800141 # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
142
143 def execute( self, **execparams ):
144 """
adminbae64d82013-08-01 10:50:15 -0700145 It facilitates the command line execution of a given command. It has arguments as :
146 cmd => represents command to be executed,
147 prompt => represents expect command prompt or output,
148 timeout => timeout for command execution,
149 more => to provide a key press if it is on.
150
151 It will return output of command exection.
kelvin8ec71442015-01-15 16:57:00 -0800152 """
153 result = super( CLI, self ).execute( self )
adminaef00552014-05-08 09:18:36 -0700154 defaultPrompt = '.*[$>\#]'
kelvin8ec71442015-01-15 16:57:00 -0800155 args = utilities.parse_args( [
acsmars07f9d392015-07-15 10:30:58 -0700156 "CMD",
kelvin8ec71442015-01-15 16:57:00 -0800157 "TIMEOUT",
158 "PROMPT",
159 "MORE" ],
acsmars07f9d392015-07-15 10:30:58 -0700160 **execparams )
kelvin8ec71442015-01-15 16:57:00 -0800161
162 expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
adminbae64d82013-08-01 10:50:15 -0700163 self.LASTRSP = ""
kelvin8ec71442015-01-15 16:57:00 -0800164 timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
adminbae64d82013-08-01 10:50:15 -0700165 cmd = ''
kelvin8ec71442015-01-15 16:57:00 -0800166 if args[ "CMD" ]:
167 cmd = args[ "CMD" ]
168 else:
adminbae64d82013-08-01 10:50:15 -0700169 return 0
kelvin8ec71442015-01-15 16:57:00 -0800170 if args[ "MORE" ] is None:
171 args[ "MORE" ] = " "
172 self.handle.sendline( cmd )
adminbae64d82013-08-01 10:50:15 -0700173 self.lastCommand = cmd
kelvin8ec71442015-01-15 16:57:00 -0800174 index = self.handle.expect( [
acsmars07f9d392015-07-15 10:30:58 -0700175 expectPrompt,
kelvin8ec71442015-01-15 16:57:00 -0800176 "--More--",
177 'Command not found.',
178 pexpect.TIMEOUT,
179 "^:$" ],
acsmars07f9d392015-07-15 10:30:58 -0700180 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
184 main.log.info(
185 "Executed :" + str(
186 cmd ) + " \t\t Expected Prompt '" + str(
187 expectPrompt) + "' Found" )
adminbae64d82013-08-01 10:50:15 -0700188 elif index == 1:
189 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800190 self.handle.send( args[ "MORE" ] )
191 main.log.info(
192 "Found More screen to go , Sending a key to proceed" )
193 indexMore = self.handle.expect(
194 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700195 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800196 main.log.info(
197 "Found anoother More screen to go , Sending a key to proceed" )
198 self.handle.send( args[ "MORE" ] )
199 indexMore = self.handle.expect(
200 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700201 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800202 elif index == 2:
203 main.log.error( "Command not found" )
adminbae64d82013-08-01 10:50:15 -0700204 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800205 elif index == 3:
206 main.log.error( "Expected Prompt not found , Time Out!!" )
207 main.log.error( expectPrompt )
adminbae64d82013-08-01 10:50:15 -0700208 return "Expected Prompt not found , Time Out!!"
kelvin8ec71442015-01-15 16:57:00 -0800209
adminbae64d82013-08-01 10:50:15 -0700210 elif index == 4:
211 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800212 # self.handle.send( args[ "MORE" ] )
213 self.handle.sendcontrol( "D" )
214 main.log.info(
215 "Found More screen to go , Sending a key to proceed" )
216 indexMore = self.handle.expect(
217 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700218 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800219 main.log.info(
220 "Found another More screen to go , Sending a key to proceed" )
221 self.handle.sendcontrol( "D" )
222 indexMore = self.handle.expect(
223 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700224 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800225
226 main.last_response = self.remove_contol_chars( self.LASTRSP )
adminbae64d82013-08-01 10:50:15 -0700227 return self.LASTRSP
kelvin8ec71442015-01-15 16:57:00 -0800228
229 def remove_contol_chars( self, response ):
230 # 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 ) )
231 # response = re.sub( RE_XML_ILLEGAL, "\n", response )
232 response = re.sub( r"[\x01-\x1F\x7F]", "", response )
233 # response = re.sub( r"\[\d+\;1H", "\n", response )
234 response = re.sub( r"\[\d+\;\d+H", "", response )
adminbae64d82013-08-01 10:50:15 -0700235 return response
adminbae64d82013-08-01 10:50:15 -0700236
kelvin8ec71442015-01-15 16:57:00 -0800237 def runAsSudoUser( self, handle, pwd, default ):
238
239 i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
240 if i == 0:
241 handle.sendline( pwd )
242 handle.sendline( "\r" )
243
244 if i == 1:
245 handle.expect( default )
246
247 if i == 2:
248 main.log.error( "Unable to run as Sudo user" )
249
adminbae64d82013-08-01 10:50:15 -0700250 return handle
adminbae64d82013-08-01 10:50:15 -0700251
kelvin8ec71442015-01-15 16:57:00 -0800252 def onfail( self ):
253 if 'onfail' in main.componentDictionary[ self.name ]:
254 commandList = main.componentDictionary[
255 self.name ][ 'onfail' ].split( "," )
256 for command in commandList:
257 response = self.execute(
258 cmd=command,
259 prompt="(.*)",
260 timeout=120 )
adminbae64d82013-08-01 10:50:15 -0700261
kelvin8ec71442015-01-15 16:57:00 -0800262 def secureCopy( self, user_name, ip_address, filepath, pwd, dst_path ):
263
264 # scp openflow@192.168.56.101:/home/openflow/sample
265 # /home/paxterra/Desktop/
266 """
adminbae64d82013-08-01 10:50:15 -0700267 Connection will establish to the remote host using ssh.
268 It will take user_name ,ip_address and password as arguments<br>
kelvin8ec71442015-01-15 16:57:00 -0800269 and will return the handle.
270 """
adminbae64d82013-08-01 10:50:15 -0700271 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -0800272 refused = "ssh: connect to host " + \
273 ip_address + " port 22: Connection refused"
acsmars07f9d392015-07-15 10:30:58 -0700274
275 cmd = 'scp ' + str( user_name ) + '@' + str( ip_address ) + ':' + \
276 str( filepath ) + ' ' + str(dst_path )
kelvin8ec71442015-01-15 16:57:00 -0800277
278 main.log.info( "Sending: " + cmd )
279 self.handle = pexpect.spawn( cmd )
280 i = self.handle.expect( [
acsmars07f9d392015-07-15 10:30:58 -0700281 ssh_newkey,
282 'password:',
283 pexpect.EOF,
284 pexpect.TIMEOUT,
285 refused ],
286 120 )
kelvin8ec71442015-01-15 16:57:00 -0800287
288 if i == 0:
289 main.log.info( "ssh key confirmation received, send yes" )
290 self.handle.sendline( 'yes' )
291 i = self.handle.expect( [ ssh_newkey, 'password:', pexpect.EOF ] )
292 if i == 1:
293 main.log.info( "ssh connection asked for password, gave password" )
294 self.handle.sendline( pwd )
295 # self.handle.expect( user_name )
296
297 elif i == 2:
298 main.log.error( "Connection timeout" )
adminbae64d82013-08-01 10:50:15 -0700299 pass
kelvin8ec71442015-01-15 16:57:00 -0800300 elif i == 3: # timeout
301 main.log.error(
302 "No route to the Host " +
303 user_name +
304 "@" +
305 ip_address )
adminbae64d82013-08-01 10:50:15 -0700306 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -0800307 elif i == 4:
308 main.log.error(
309 "ssh: connect to host " +
310 ip_address +
311 " port 22: Connection refused" )
adminbae64d82013-08-01 10:50:15 -0700312 return main.FALSE
313
kelvin8ec71442015-01-15 16:57:00 -0800314 self.handle.sendline( "" )
315 self.handle.expect( "$" )
Jon Hall94fd0472014-12-08 11:52:42 -0800316 print self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800317
adminbae64d82013-08-01 10:50:15 -0700318 return self.handle