blob: 002d53c4b178aea6f5a2169bed64149c0e163a70 [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 '>|#|\$' ],
90 120 )
acsmars71da6542015-06-30 09:36:36 -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' )
acsmars71da6542015-06-30 09:36:36 -070094 i = 5 #Run the loop again
acsmarse2be32c2015-06-29 16:16:28 -070095 continue
kelvin8ec71442015-01-15 16:57:00 -080096 if i == 1:
Jon Hall63604932015-02-26 17:09:50 -080097 if self.pwd:
98 main.log.info(
99 "ssh connection asked for password, gave password" )
100 self.handle.sendline( self.pwd )
101 self.handle.expect( '>|#|\$' )
102 else:
103 # FIXME: TestON does not support a username having no
104 # password
105 main.log.error( "Server asked for password, but none was "
106 "given in the .topo file" )
107 main.exit()
kelvin8ec71442015-01-15 16:57:00 -0800108 elif i == 2:
109 main.log.error( "Connection timeout" )
110 return main.FALSE
111 elif i == 3: # timeout
112 main.log.error(
113 "No route to the Host " +
114 self.user_name +
115 "@" +
116 self.ip_address )
117 return main.FALSE
118 elif i == 4:
119 main.log.error(
120 "ssh: connect to host " +
121 self.ip_address +
122 " port 22: Connection refused" )
123 return main.FALSE
124 elif i == 6:
125 main.log.info( "Password not required logged in" )
adminbae64d82013-08-01 10:50:15 -0700126
kelvin8ec71442015-01-15 16:57:00 -0800127 self.handle.sendline( "" )
128 self.handle.expect( '>|#|\$' )
adminbae64d82013-08-01 10:50:15 -0700129 return self.handle
130
kelvin8ec71442015-01-15 16:57:00 -0800131 def disconnect( self ):
132 result = super( CLI, self ).disconnect( self )
adminbae64d82013-08-01 10:50:15 -0700133 result = main.TRUE
kelvin8ec71442015-01-15 16:57:00 -0800134 # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
135
136 def execute( self, **execparams ):
137 """
adminbae64d82013-08-01 10:50:15 -0700138 It facilitates the command line execution of a given command. It has arguments as :
139 cmd => represents command to be executed,
140 prompt => represents expect command prompt or output,
141 timeout => timeout for command execution,
142 more => to provide a key press if it is on.
143
144 It will return output of command exection.
kelvin8ec71442015-01-15 16:57:00 -0800145 """
146 result = super( CLI, self ).execute( self )
adminaef00552014-05-08 09:18:36 -0700147 defaultPrompt = '.*[$>\#]'
kelvin8ec71442015-01-15 16:57:00 -0800148 args = utilities.parse_args( [
149 "CMD",
150 "TIMEOUT",
151 "PROMPT",
152 "MORE" ],
153 **execparams )
154
155 expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
adminbae64d82013-08-01 10:50:15 -0700156 self.LASTRSP = ""
kelvin8ec71442015-01-15 16:57:00 -0800157 timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
adminbae64d82013-08-01 10:50:15 -0700158 cmd = ''
kelvin8ec71442015-01-15 16:57:00 -0800159 if args[ "CMD" ]:
160 cmd = args[ "CMD" ]
161 else:
adminbae64d82013-08-01 10:50:15 -0700162 return 0
kelvin8ec71442015-01-15 16:57:00 -0800163 if args[ "MORE" ] is None:
164 args[ "MORE" ] = " "
165 self.handle.sendline( cmd )
adminbae64d82013-08-01 10:50:15 -0700166 self.lastCommand = cmd
kelvin8ec71442015-01-15 16:57:00 -0800167 index = self.handle.expect( [
168 expectPrompt,
169 "--More--",
170 'Command not found.',
171 pexpect.TIMEOUT,
172 "^:$" ],
173 timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700174 if index == 0:
kelvin8ec71442015-01-15 16:57:00 -0800175 self.LASTRSP = self.LASTRSP + \
176 self.handle.before + self.handle.after
177 main.log.info(
178 "Executed :" + str(
179 cmd ) + " \t\t Expected Prompt '" + str(
180 expectPrompt) + "' Found" )
adminbae64d82013-08-01 10:50:15 -0700181 elif index == 1:
182 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800183 self.handle.send( args[ "MORE" ] )
184 main.log.info(
185 "Found More screen to go , Sending a key to proceed" )
186 indexMore = self.handle.expect(
187 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700188 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800189 main.log.info(
190 "Found anoother More screen to go , Sending a key to proceed" )
191 self.handle.send( args[ "MORE" ] )
192 indexMore = self.handle.expect(
193 [ "--More--", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700194 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800195 elif index == 2:
196 main.log.error( "Command not found" )
adminbae64d82013-08-01 10:50:15 -0700197 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800198 elif index == 3:
199 main.log.error( "Expected Prompt not found , Time Out!!" )
200 main.log.error( expectPrompt )
adminbae64d82013-08-01 10:50:15 -0700201 return "Expected Prompt not found , Time Out!!"
kelvin8ec71442015-01-15 16:57:00 -0800202
adminbae64d82013-08-01 10:50:15 -0700203 elif index == 4:
204 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800205 # self.handle.send( args[ "MORE" ] )
206 self.handle.sendcontrol( "D" )
207 main.log.info(
208 "Found More screen to go , Sending a key to proceed" )
209 indexMore = self.handle.expect(
210 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700211 while indexMore == 0:
kelvin8ec71442015-01-15 16:57:00 -0800212 main.log.info(
213 "Found another More screen to go , Sending a key to proceed" )
214 self.handle.sendcontrol( "D" )
215 indexMore = self.handle.expect(
216 [ "^:$", expectPrompt ], timeout=timeoutVar )
adminbae64d82013-08-01 10:50:15 -0700217 self.LASTRSP = self.LASTRSP + self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800218
219 main.last_response = self.remove_contol_chars( self.LASTRSP )
adminbae64d82013-08-01 10:50:15 -0700220 return self.LASTRSP
kelvin8ec71442015-01-15 16:57:00 -0800221
222 def remove_contol_chars( self, response ):
223 # 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 ) )
224 # response = re.sub( RE_XML_ILLEGAL, "\n", response )
225 response = re.sub( r"[\x01-\x1F\x7F]", "", response )
226 # response = re.sub( r"\[\d+\;1H", "\n", response )
227 response = re.sub( r"\[\d+\;\d+H", "", response )
adminbae64d82013-08-01 10:50:15 -0700228 return response
adminbae64d82013-08-01 10:50:15 -0700229
kelvin8ec71442015-01-15 16:57:00 -0800230 def runAsSudoUser( self, handle, pwd, default ):
231
232 i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
233 if i == 0:
234 handle.sendline( pwd )
235 handle.sendline( "\r" )
236
237 if i == 1:
238 handle.expect( default )
239
240 if i == 2:
241 main.log.error( "Unable to run as Sudo user" )
242
adminbae64d82013-08-01 10:50:15 -0700243 return handle
adminbae64d82013-08-01 10:50:15 -0700244
kelvin8ec71442015-01-15 16:57:00 -0800245 def onfail( self ):
246 if 'onfail' in main.componentDictionary[ self.name ]:
247 commandList = main.componentDictionary[
248 self.name ][ 'onfail' ].split( "," )
249 for command in commandList:
250 response = self.execute(
251 cmd=command,
252 prompt="(.*)",
253 timeout=120 )
adminbae64d82013-08-01 10:50:15 -0700254
kelvin8ec71442015-01-15 16:57:00 -0800255 def secureCopy( self, user_name, ip_address, filepath, pwd, dst_path ):
256
257 # scp openflow@192.168.56.101:/home/openflow/sample
258 # /home/paxterra/Desktop/
259 """
adminbae64d82013-08-01 10:50:15 -0700260 Connection will establish to the remote host using ssh.
261 It will take user_name ,ip_address and password as arguments<br>
kelvin8ec71442015-01-15 16:57:00 -0800262 and will return the handle.
263 """
adminbae64d82013-08-01 10:50:15 -0700264 ssh_newkey = 'Are you sure you want to continue connecting'
kelvin8ec71442015-01-15 16:57:00 -0800265 refused = "ssh: connect to host " + \
266 ip_address + " port 22: Connection refused"
adminbae64d82013-08-01 10:50:15 -0700267
kelvin8ec71442015-01-15 16:57:00 -0800268 cmd = 'scp ' + str( user_name ) + '@' + str( ip_address ) + ':' + \
269 str( filepath ) + ' ' + str(dst_path )
270
271 main.log.info( "Sending: " + cmd )
272 self.handle = pexpect.spawn( cmd )
273 i = self.handle.expect( [
274 ssh_newkey,
275 'password:',
276 pexpect.EOF,
277 pexpect.TIMEOUT,
278 refused ],
279 120 )
280
281 if i == 0:
282 main.log.info( "ssh key confirmation received, send yes" )
283 self.handle.sendline( 'yes' )
284 i = self.handle.expect( [ ssh_newkey, 'password:', pexpect.EOF ] )
285 if i == 1:
286 main.log.info( "ssh connection asked for password, gave password" )
287 self.handle.sendline( pwd )
288 # self.handle.expect( user_name )
289
290 elif i == 2:
291 main.log.error( "Connection timeout" )
adminbae64d82013-08-01 10:50:15 -0700292 pass
kelvin8ec71442015-01-15 16:57:00 -0800293 elif i == 3: # timeout
294 main.log.error(
295 "No route to the Host " +
296 user_name +
297 "@" +
298 ip_address )
adminbae64d82013-08-01 10:50:15 -0700299 return main.FALSE
kelvin8ec71442015-01-15 16:57:00 -0800300 elif i == 4:
301 main.log.error(
302 "ssh: connect to host " +
303 ip_address +
304 " port 22: Connection refused" )
adminbae64d82013-08-01 10:50:15 -0700305 return main.FALSE
306
kelvin8ec71442015-01-15 16:57:00 -0800307 self.handle.sendline( "" )
308 self.handle.expect( "$" )
Jon Hall94fd0472014-12-08 11:52:42 -0800309 print self.handle.before
kelvin8ec71442015-01-15 16:57:00 -0800310
adminbae64d82013-08-01 10:50:15 -0700311 return self.handle
kelvin8ec71442015-01-15 16:57:00 -0800312