blob: c46addd9fa13e688ecad160acfe1f34ec8f832f7 [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( [
acsmars248c04d2015-06-29 15:00:17 -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 '>|#|\$' ],
90 120 )
91 if i == 0:
92 main.log.info( "ssh key confirmation received, send yes" )
93 self.handle.sendline( 'yes' )
acsmars248c04d2015-06-29 15:00:17 -070094 continue #Expect either a password prompt or access
kelvin8ec71442015-01-15 16:57:00 -080095 if i == 1:
Jon Hall63604932015-02-26 17:09:50 -080096 if self.pwd:
97 main.log.info(
98 "ssh connection asked for password, gave password" )
99 self.handle.sendline( self.pwd )
100 self.handle.expect( '>|#|\$' )
101 else:
102 # FIXME: TestON does not support a username having no
103 # password
104 main.log.error( "Server asked for password, but none was "
105 "given in the .topo file" )
106 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800107 elif i == 2:
108 main.log.error( "Connection timeout" )
109 return main.FALSE
110 elif i == 3: # timeout
111 main.log.error(
112 "No route to the Host " +
113 self.user_name +
114 "@" +
115 self.ip_address )
116 return main.FALSE
117 elif i == 4:
118 main.log.error(
119 "ssh: connect to host " +
120 self.ip_address +
121 " port 22: Connection refused" )
122 return main.FALSE
123 elif i == 6:
124 main.log.info( "Password not required logged in" )
adminbae64d82013-08-01 10:50:15 -0700125
kelvin8ec71442015-01-15 16:57:00 -0800126 self.handle.sendline( "" )
127 self.handle.expect( '>|#|\$' )
adminbae64d82013-08-01 10:50:15 -0700128 return self.handle
129
kelvin8ec71442015-01-15 16:57:00 -0800130 def disconnect( self ):
131 result = super( CLI, self ).disconnect( self )
adminbae64d82013-08-01 10:50:15 -0700132 result = main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800133 # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
134
135 def execute( self, **execparams ):
136 """
adminbae64d82013-08-01 10:50:15 -0700137 It facilitates the command line execution of a given command. It has arguments as :
138 cmd => represents command to be executed,
139 prompt => represents expect command prompt or output,
140 timeout => timeout for command execution,
141 more => to provide a key press if it is on.
142
143 It will return output of command exection.
kelvin8ec71442015-01-15 16:57:00 -0800144 """
145 result = super( CLI, self ).execute( self )
adminaef00552014-05-08 09:18:36 -0700146 defaultPrompt = '.*[$>\#]'
kelvin8ec71442015-01-15 16:57:00 -0800147 args = utilities.parse_args( [
148 "CMD",
149 "TIMEOUT",
150 "PROMPT",
151 "MORE" ],
152 **execparams )
153
154 expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
adminbae64d82013-08-01 10:50:15 -0700155 self.LASTRSP = ""
kelvin8ec71442015-01-15 16:57:00 -0800156 timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
adminbae64d82013-08-01 10:50:15 -0700157 cmd = ''
kelvin8ec71442015-01-15 16:57:00 -0800158 if args[ "CMD" ]:
159 cmd = args[ "CMD" ]
160 else:
adminbae64d82013-08-01 10:50:15 -0700161 return 0
kelvin8ec71442015-01-15 16:57:00 -0800162 if args[ "MORE" ] is None:
163 args[ "MORE" ] = " "
164 self.handle.sendline( cmd )
adminbae64d82013-08-01 10:50:15 -0700165 self.lastCommand = cmd
kelvin8ec71442015-01-15 16:57:00 -0800166 index = self.handle.expect( [
167 expectPrompt,
168 "--More--",
169 'Command not found.',
170 pexpect.TIMEOUT,
171 "^:$" ],
172 timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700173 if index == 0:
kelvin8ec71442015-01-15 16:57:00 -0800174 self.LASTRSP = self.LASTRSP + \
175 self.handle.before + self.handle.after
176 main.log.info(
177 "Executed :" + str(
178 cmd ) + " \t\t Expected Prompt '" + str(
179 expectPrompt) + "' Found" )
adminbae64d82013-08-01 10:50:15 -0700180 elif index == 1:
181 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800182 self.handle.send( args[ "MORE" ] )
183 main.log.info(
184 "Found More screen to go , Sending a key to proceed" )
185 indexMore = self.handle.expect(
186 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700187 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800188 main.log.info(
189 "Found anoother More screen to go , Sending a key to proceed" )
190 self.handle.send( args[ "MORE" ] )
191 indexMore = self.handle.expect(
192 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700193 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800194 elif index == 2:
195 main.log.error( "Command not found" )
adminbae64d82013-08-01 10:50:15 -0700196 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800197 elif index == 3:
198 main.log.error( "Expected Prompt not found , Time Out!!" )
199 main.log.error( expectPrompt )
adminbae64d82013-08-01 10:50:15 -0700200 return "Expected Prompt not found , Time Out!!"
kelvin8ec71442015-01-15 16:57:00 -0800201
adminbae64d82013-08-01 10:50:15 -0700202 elif index == 4:
203 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800204 # self.handle.send( args[ "MORE" ] )
205 self.handle.sendcontrol( "D" )
206 main.log.info(
207 "Found More screen to go , Sending a key to proceed" )
208 indexMore = self.handle.expect(
209 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700210 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800211 main.log.info(
212 "Found another More screen to go , Sending a key to proceed" )
213 self.handle.sendcontrol( "D" )
214 indexMore = self.handle.expect(
215 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700216 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800217
218 main.last_response = self.remove_contol_chars( self.LASTRSP )
adminbae64d82013-08-01 10:50:15 -0700219 return self.LASTRSP
kelvin8ec71442015-01-15 16:57:00 -0800220
221 def remove_contol_chars( self, response ):
222 # 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 ) )
223 # response = re.sub( RE_XML_ILLEGAL, "\n", response )
224 response = re.sub( r"[\x01-\x1F\x7F]", "", response )
225 # response = re.sub( r"\[\d+\;1H", "\n", response )
226 response = re.sub( r"\[\d+\;\d+H", "", response )
adminbae64d82013-08-01 10:50:15 -0700227 return response
adminbae64d82013-08-01 10:50:15 -0700228
kelvin8ec71442015-01-15 16:57:00 -0800229 def runAsSudoUser( self, handle, pwd, default ):
230
231 i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
232 if i == 0:
233 handle.sendline( pwd )
234 handle.sendline( "\r" )
235
236 if i == 1:
237 handle.expect( default )
238
239 if i == 2:
240 main.log.error( "Unable to run as Sudo user" )
241
adminbae64d82013-08-01 10:50:15 -0700242 return handle
adminbae64d82013-08-01 10:50:15 -0700243
kelvin8ec71442015-01-15 16:57:00 -0800244 def onfail( self ):
245 if 'onfail' in main.componentDictionary[ self.name ]:
246 commandList = main.componentDictionary[
247 self.name ][ 'onfail' ].split( "," )
248 for command in commandList:
249 response = self.execute(
250 cmd=command,
251 prompt="(.*)",
252 timeout=120 )
adminbae64d82013-08-01 10:50:15 -0700253
kelvin8ec71442015-01-15 16:57:00 -0800254 def secureCopy( self, user_name, ip_address, filepath, pwd, dst_path ):
255
256 # scp openflow@192.168.56.101:/home/openflow/sample
257 # /home/paxterra/Desktop/
258 """
adminbae64d82013-08-01 10:50:15 -0700259 Connection will establish to the remote host using ssh.
260 It will take user_name ,ip_address and password as arguments<br>
kelvin8ec71442015-01-15 16:57:00 -0800261 and will return the handle.
262 """
adminbae64d82013-08-01 10:50:15 -0700263 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -0800264 refused = "ssh: connect to host " + \
265 ip_address + " port 22: Connection refused"
adminbae64d82013-08-01 10:50:15 -0700266
kelvin8ec71442015-01-15 16:57:00 -0800267 cmd = 'scp ' + str( user_name ) + '@' + str( ip_address ) + ':' + \
268 str( filepath ) + ' ' + str(dst_path )
269
270 main.log.info( "Sending: " + cmd )
271 self.handle = pexpect.spawn( cmd )
272 i = self.handle.expect( [
273 ssh_newkey,
274 'password:',
275 pexpect.EOF,
276 pexpect.TIMEOUT,
277 refused ],
278 120 )
279
280 if i == 0:
281 main.log.info( "ssh key confirmation received, send yes" )
282 self.handle.sendline( 'yes' )
283 i = self.handle.expect( [ ssh_newkey, 'password:', pexpect.EOF ] )
284 if i == 1:
285 main.log.info( "ssh connection asked for password, gave password" )
286 self.handle.sendline( pwd )
287 # self.handle.expect( user_name )
288
289 elif i == 2:
290 main.log.error( "Connection timeout" )
adminbae64d82013-08-01 10:50:15 -0700291 pass
kelvin8ec71442015-01-15 16:57:00 -0800292 elif i == 3: # timeout
293 main.log.error(
294 "No route to the Host " +
295 user_name +
296 "@" +
297 ip_address )
adminbae64d82013-08-01 10:50:15 -0700298 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -0800299 elif i == 4:
300 main.log.error(
301 "ssh: connect to host " +
302 ip_address +
303 " port 22: Connection refused" )
adminbae64d82013-08-01 10:50:15 -0700304 return main.FALSE
305
kelvin8ec71442015-01-15 16:57:00 -0800306 self.handle.sendline( "" )
307 self.handle.expect( "$" )
Jon Hall94fd0472014-12-08 11:52:42 -0800308 print self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800309
adminbae64d82013-08-01 10:50:15 -0700310 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800311