Introduce ONOS cli interface adapted from TestON project.
This is made to work with cord tester through a wrapper: clicommon.py
Also change the cord-tester docker image builder to include dependencies for the ONOS cli interface.
diff --git a/src/test/cli/clidriver.py b/src/test/cli/clidriver.py
new file mode 100644
index 0000000..ce10a2c
--- /dev/null
+++ b/src/test/cli/clidriver.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python
+"""
+Created on 24-Oct-2012
+
+author:s: Anil Kumar ( anilkumar.s@paxterrasolutions.com ),
+ Raghav Kashyap( raghavkashyap@paxterrasolutions.com )
+
+
+ TestON is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ ( at your option ) any later version.
+
+ TestON is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
+
+
+
+"""
+import pexpect
+import re
+from component import Component
+from clicommon import *
+import os
+
+class CLI( Component ):
+
+ """
+ This will define common functions for CLI included.
+ """
+ def __init__( self ):
+ super( Component, self ).__init__()
+
+ def connect( self, **connectargs ):
+ """
+ Connection will establish to the remote host using ssh.
+ It will take user_name ,ip_address and password as arguments<br>
+ and will return the handle.
+ """
+ for key in connectargs:
+ vars( self )[ key ] = connectargs[ key ]
+
+ connect_result = super( CLI, self ).connect()
+ ssh_newkey = 'Are you sure you want to continue connecting'
+ refused = "ssh: connect to host " + \
+ self.ip_address + " port 22: Connection refused"
+ if self.port:
+ ssh_hosts_file = os.path.join(os.getenv('HOME'), '.ssh', 'known_hosts')
+ cmd_host_remove = 'ssh-keygen -f "%s" -R [%s]:8101' %(ssh_hosts_file, self.ip_address)
+ #os.system(cmd_host_remove)
+ #main.log.info('SSH host remove cmd: %s' %cmd_host_remove)
+ main.log.info('Spawning pexpect for ip %s' %self.ip_address)
+ self.handle = pexpect.spawn(
+ 'ssh -p ' +
+ self.port +
+ ' ' +
+ '-o StrictHostKeyChecking=no ' +
+ self.user_name +
+ '@' +
+ self.ip_address,
+ env={ "TERM": "xterm-mono" },
+ maxread=50000 )
+ else:
+ self.handle = pexpect.spawn(
+ 'ssh -X ' +
+ self.user_name +
+ '@' +
+ self.ip_address,
+ env={ "TERM": "xterm-mono" },
+ maxread=1000000,
+ timeout=60 )
+
+ self.handle.logfile = self.logfile_handler
+ i = 5
+ while i == 5:
+ i = self.handle.expect( [
+ ssh_newkey,
+ 'password:|Password:',
+ pexpect.EOF,
+ pexpect.TIMEOUT,
+ refused,
+ 'teston>',
+ '>|#|\$' ],
+ 120 )
+ if i == 0: # Accept key, then expect either a password prompt or access
+ main.log.info( "ssh key confirmation received, send yes" )
+ self.handle.sendline( 'yes' )
+ i = 5 # Run the loop again
+ continue
+ if i == 1: # Password required
+ if self.pwd:
+ main.log.info(
+ "ssh connection asked for password, gave password" )
+ else:
+ main.log.info( "Server asked for password, but none was "
+ "given in the .topo file. Trying "
+ "no password.")
+ self.pwd = ""
+ self.handle.sendline( self.pwd )
+ j = self.handle.expect( [
+ '>|#|\$',
+ 'password:|Password:',
+ pexpect.EOF,
+ pexpect.TIMEOUT ],
+ 120 )
+ if j != 0:
+ main.log.error( "Incorrect Password" )
+ return main.FALSE
+ elif i == 2:
+ main.log.error( "Connection timeout" )
+ return main.FALSE
+ elif i == 3: # timeout
+ main.log.error(
+ "No route to the Host " +
+ self.user_name +
+ "@" +
+ self.ip_address )
+ return main.FALSE
+ elif i == 4:
+ main.log.error(
+ "ssh: connect to host " +
+ self.ip_address +
+ " port 22: Connection refused" )
+ return main.FALSE
+ elif i == 6:
+ main.log.info( "Password not required logged in" )
+
+ self.handle.sendline( "" )
+ self.handle.expect( '>|#|\$' )
+ return self.handle
+
+ def disconnect( self ):
+ result = super( CLI, self ).disconnect( self )
+ result = main.TRUE
+ # self.execute( cmd="exit",timeout=120,prompt="(.*)" )
+
+ def execute( self, **execparams ):
+ """
+ It facilitates the command line execution of a given command. It has arguments as :
+ cmd => represents command to be executed,
+ prompt => represents expect command prompt or output,
+ timeout => timeout for command execution,
+ more => to provide a key press if it is on.
+
+ It will return output of command exection.
+ """
+ result = super( CLI, self ).execute( self )
+ defaultPrompt = '.*[$>\#]'
+ args = utilities.parse_args( [ "CMD",
+ "TIMEOUT",
+ "PROMPT",
+ "MORE" ],
+ **execparams )
+
+ expectPrompt = args[ "PROMPT" ] if args[ "PROMPT" ] else defaultPrompt
+ self.LASTRSP = ""
+ timeoutVar = args[ "TIMEOUT" ] if args[ "TIMEOUT" ] else 10
+ cmd = ''
+ if args[ "CMD" ]:
+ cmd = args[ "CMD" ]
+ else:
+ return 0
+ if args[ "MORE" ] is None:
+ args[ "MORE" ] = " "
+ self.handle.sendline( cmd )
+ self.lastCommand = cmd
+ index = self.handle.expect( [ expectPrompt,
+ "--More--",
+ 'Command not found.',
+ pexpect.TIMEOUT,
+ "^:$" ],
+ timeout=timeoutVar )
+ if index == 0:
+ self.LASTRSP = self.LASTRSP + \
+ self.handle.before + self.handle.after
+ main.log.info( "Executed :" + str(cmd ) +
+ " \t\t Expected Prompt '" + str( expectPrompt) +
+ "' Found" )
+ elif index == 1:
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ self.handle.send( args[ "MORE" ] )
+ main.log.info(
+ "Found More screen to go , Sending a key to proceed" )
+ indexMore = self.handle.expect(
+ [ "--More--", expectPrompt ], timeout=timeoutVar )
+ while indexMore == 0:
+ main.log.info(
+ "Found anoother More screen to go , Sending a key to proceed" )
+ self.handle.send( args[ "MORE" ] )
+ indexMore = self.handle.expect(
+ [ "--More--", expectPrompt ], timeout=timeoutVar )
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ elif index == 2:
+ main.log.error( "Command not found" )
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ elif index == 3:
+ main.log.error( "Expected Prompt not found, Time Out!!" )
+ main.log.error( expectPrompt )
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ return self.LASTRSP
+ elif index == 4:
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ # self.handle.send( args[ "MORE" ] )
+ self.handle.sendcontrol( "D" )
+ main.log.info(
+ "Found More screen to go, Sending a key to proceed" )
+ indexMore = self.handle.expect(
+ [ "^:$", expectPrompt ], timeout=timeoutVar )
+ while indexMore == 0:
+ main.log.info(
+ "Found another More screen to go, Sending a key to proceed" )
+ self.handle.sendcontrol( "D" )
+ indexMore = self.handle.expect(
+ [ "^:$", expectPrompt ], timeout=timeoutVar )
+ self.LASTRSP = self.LASTRSP + self.handle.before
+ main.last_response = self.remove_contol_chars( self.LASTRSP )
+ return self.LASTRSP
+
+ def remove_contol_chars( self, response ):
+ # 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 ) )
+ # response = re.sub( RE_XML_ILLEGAL, "\n", response )
+ response = re.sub( r"[\x01-\x1F\x7F]", "", response )
+ # response = re.sub( r"\[\d+\;1H", "\n", response )
+ response = re.sub( r"\[\d+\;\d+H", "", response )
+ return response
+
+ def runAsSudoUser( self, handle, pwd, default ):
+
+ i = handle.expect( [ ".ssword:*", default, pexpect.EOF ] )
+ if i == 0:
+ handle.sendline( pwd )
+ handle.sendline( "\n" )
+
+ if i == 1:
+ handle.expect( default )
+
+ if i == 2:
+ main.log.error( "Unable to run as Sudo user" )
+
+ return handle
+
+ def onfail( self ):
+ if 'onfail' in main.componentDictionary[ self.name ]:
+ commandList = main.componentDictionary[
+ self.name ][ 'onfail' ].split( "," )
+ for command in commandList:
+ response = self.execute(
+ cmd=command,
+ prompt="(.*)",
+ timeout=120 )
+
+ def secureCopy( self, userName, ipAddress, filePath, dstPath, pwd="",
+ direction="from" ):
+ """
+ Definition:
+ Execute scp command in linux to copy to/from a remote host
+ Required:
+ str userName - User name of the remote host
+ str ipAddress - IP address of the remote host
+ str filePath - File path including the file it self
+ str dstPath - Destination path
+ Optional:
+ str pwd - Password of the host
+ str direction - Direction of the scp, default to "from" which means
+ copy "from" the remote machine to local machine,
+ while "to" means copy "to" the remote machine from
+ local machine
+ """
+ returnVal = main.TRUE
+ ssh_newkey = 'Are you sure you want to continue connecting'
+ refused = "ssh: connect to host " + \
+ ipAddress + " port 22: Connection refused"
+
+ if direction == "from":
+ cmd = 'scp ' + str( userName ) + '@' + str( ipAddress ) + ':' + \
+ str( filePath ) + ' ' + str( dstPath )
+ elif direction == "to":
+ cmd = 'scp ' + str( filePath ) + ' ' + str( userName ) + \
+ '@' + str( ipAddress ) + ':' + str( dstPath )
+ else:
+ main.log.debug( "Wrong direction using secure copy command!" )
+ return main.FALSE
+
+ main.log.info( "Sending: " + cmd )
+ self.handle.sendline( cmd )
+ i = 0
+ while i < 2:
+ i = self.handle.expect( [
+ ssh_newkey,
+ 'password:',
+ "100%",
+ refused,
+ "No such file or directory",
+ pexpect.EOF,
+ pexpect.TIMEOUT ],
+ 120 )
+ if i == 0: # ask for ssh key confirmation
+ main.log.info( "ssh key confirmation received, sending yes" )
+ self.handle.sendline( 'yes' )
+ elif i == 1: # Asked for ssh password
+ main.log.info( "ssh connection asked for password, gave password" )
+ self.handle.sendline( pwd )
+ elif i == 2: # File finished transfering
+ main.log.info( "Secure copy successful" )
+ returnVal = main.TRUE
+ elif i == 3: # Connection refused
+ main.log.error(
+ "ssh: connect to host " +
+ ipAddress +
+ " port 22: Connection refused" )
+ returnVal = main.FALSE
+ elif i == 4: # File Not found
+ main.log.error( "No such file found" )
+ returnVal = main.FALSE
+ elif i == 5: # EOF
+ main.log.error( "Pexpect.EOF found!!!" )
+ main.cleanup()
+ main.exit()
+ elif i == 6: # timeout
+ main.log.error(
+ "No route to the Host " +
+ userName +
+ "@" +
+ ipAddress )
+ returnVal = main.FALSE
+ self.handle.expect( "\$" )
+ return returnVal
+
+ def scp( self, remoteHost, filePath, dstPath, direction="from" ):
+ """
+ Definition:
+ Execute scp command in linux to copy to/from a remote host
+ Required:
+ * remoteHost - Test ON component to be parsed
+ str filePath - File path including the file it self
+ str dstPath - Destination path
+ Optional:
+ str direction - Direction of the scp, default to "from" which means
+ copy "from" the remote machine to local machine,
+ while "to" means copy "to" the remote machine from
+ local machine
+ """
+ return self.secureCopy( remoteHost.user_name,
+ remoteHost.ip_address,
+ filePath,
+ dstPath,
+ pwd=remoteHost.pwd,
+ direction=direction )