blob: 149007983ff7e13e1677e45b52ed2ad5d3e05fcc [file] [log] [blame]
#!/usr/bin/env python
"""
Copyright 2020 Open Networking Foundation (ONF)
Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
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 types
import os
from drivers.common.clidriver import CLI
class StratumOSSwitchDriver( CLI ):
def __init__( self ):
"""
Initialize client
"""
super( CLI, self ).__init__()
self.name = None
self.shortName = None
self.handle = None
self.prompt = "~(/TestON)?#"
self.dockerPrompt = "/run/stratum#"
self.home = "/root"
# Local home for functions using scp
self.tempDirectory = "/tmp/"
self.ports = []
self.isup = True
def connect( self, **connectargs ):
"""
Creates ssh handle for cli.
"""
try:
# Parse keys in xml object
for key in connectargs:
vars( self )[ key ] = connectargs[ key ]
# Get the name
self.name = self.options[ 'name' ]
self.shortName = self.options[ 'shortName' ]
# Parse the IP address
try:
if os.getenv( str( self.ip_address ) ) is not None:
self.ip_address = os.getenv( str( self.ip_address ) )
# Otherwise is an ip address
else:
main.log.info( self.name + ": Trying to connect to " + self.ip_address )
# Error handling
except KeyError:
main.log.info( "Invalid host name," + " connecting to local host instead" )
self.ip_address = 'localhost'
except Exception as inst:
main.log.error( "Uncaught exception: " + str( inst ) )
self.handle = super( StratumOSSwitchDriver, self ).connect(
user_name=self.user_name,
ip_address=self.ip_address,
port=None,
pwd=self.pwd)
# Successful connection
if self.handle:
main.log.info( "Connection successful to the host " + self.user_name + "@" + self.ip_address )
self.handle.sendline( "" )
self.handle.expect( self.prompt )
return main.TRUE
# Connection failed
else:
main.log.error( "Connection failed to the host " + self.user_name + "@" + self.ip_address )
main.log.error( "Failed to connect to the Stratum Switch" )
return main.FALSE
# Error handling
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
return None
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanup()
main.exit()
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
def disconnect( self ):
"""
Called when Test is complete to disconnect the component handle.
"""
response = main.TRUE
try:
if self.handle:
# Stop the agent
if not main.persistentSetup:
self.stopSwitchAgent()
main.log.debug( self.name + ": Disconnected" )
# Disconnect from the device
self.handle.sendline( "" )
self.handle.expect( self.prompt )
self.handle.sendline( "exit" )
self.handle.expect( "closed" )
# Errors handling
except pexpect.TIMEOUT:
main.log.error( self.name + ": pexpect.TIMEOUT found" )
main.log.debug( self.handle.before )
return main.FALSE
except TypeError:
main.log.exception( self.name + ": Object not as expected" )
response = main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
except ValueError:
main.log.exception( "Exception in disconnect of " + self.name )
response = main.TRUE
except Exception:
main.log.exception( self.name + ": Connection failed to the host" )
response = main.FALSE
return response
def assignSwController( self, ip, updateConf=True, **kwargs ):
"""
Description:
Edit the config file for the switch and upload it to the onos
controller to connect the switch and controller
NOTE that this function is available on all switch drivers,
and the name is a hold over from ovs switches.
kwargs contains any arguments for other types of switches
Required:
ip - Ip addresses of controllers. This can be a list or a string.
updateConf - whether to pull and update configurations and scripts
Return:
Returns main.TRUE if the switch is correctly assigned to controllers,
otherwise it will return main.FALSE or an appropriate exception(s)
"""
assignResult = main.TRUE
onosIp = ""
# Parses the controller option
# We only need one onos ip
try:
if isinstance( ip, types.StringType ):
onosIp = str( ip )
elif isinstance( ip, types.ListType ):
onosIp = ip[ 0 ]
else:
main.log.error( self.name + ": Invalid controller ip address" )
return main.FALSE
if updateConf:
self.setupContainer()
main.ONOSbench.onosNetCfg( onosIp, self.options[ 'onosConfigPath' ], self.options[ 'onosConfigFile' ] )
assignResult = self.startSwitchAgent()
if not assignResult:
self.isup = False
else:
self.isup = True
# Done return true
return assignResult
# Errors handling
except pexpect.TIMEOUT:
main.log.error( self.name + ": pexpect.TIMEOUT found" )
return main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanAndExit()
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
def setupContainer( self ):
"""
Prepare for the container to be run. Includes pulling scripts
and modifying them
"""
try:
#TODO Remove hardcoding
main.log.info( "Creating working directory" )
self.handle.sendline( "mkdir TestON" )
self.handle.expect( self.prompt )
self.handle.sendline( "cd TestON" )
self.handle.expect( self.prompt )
main.log.info( "Getting start container script" )
# TODO: Parameterize this
self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/bin/barefoot/docker/start-stratum-container.sh" )
self.handle.expect( self.prompt )
main.log.info( "Modify start container script" )
self.handle.sendline( "sed -i '/--privileged/a \ --name stratum \\\\' start-stratum-container.sh" )
self.handle.expect( self.prompt )
# TODO: Add docker pull command to the start-stratum-container.sh script
main.log.info( "Getting chassis config" )
# TODO: Parameterize this
filename = "~/TestON/tests/USECASE/SegmentRouting/dependencies/chassis_config.pb.txt.qa"
main.ONOSbench.secureCopy( self.user_name, self.ip_address, filename, "~/TestON/chassis_config.pb.txt", pwd=self.pwd, direction="to" )
main.log.info( "Modify chassis config" )
# TODO: Parameterize this
self.handle.sendline( "export CHASSIS_CONFIG=~/TestON/chassis_config.pb.txt" )
self.handle.expect( self.prompt )
#self.handle.sendline( "export DOCKER_IMAGE=registry.aetherproject.org/tost/stratum-bfrt" )
self.handle.sendline( "export DOCKER_IMAGE=stratumproject/stratum-bf" )
self.handle.expect( self.prompt )
self.handle.sendline( "export DOCKER_IMAGE_TAG=9.2.0" )
self.handle.expect( self.prompt )
self.handle.sendline( "chmod +x start-stratum-container.sh" )
self.handle.expect( self.prompt )
except pexpect.TIMEOUT:
main.log.error( self.name + ": pexpect.TIMEOUT found" )
main.log.debug( self.handle.before )
return main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanAndExit()
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
def startSwitchAgent( self ):
"""
Start the stratum agent on the device
"""
try:
main.log.info( "Starting switch agent" )
self.handle.sendline( "./start-stratum-container.sh --bf-sim --bf-switchd-background=false" )
self.handle.expect( "Chassis config pushed successfully." )
return main.TRUE
except pexpect.TIMEOUT:
main.log.error( self.name + ": pexpect.TIMEOUT found" )
main.log.debug( self.handle.before )
return main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanAndExit()
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
def stopSwitchAgent( self ):
"""
Stop the strratum agent on the device
"""
try:
main.log.info( self.name + ": stopping Stratum Switch agent" )
while True:
self.handle.sendline( "" )
i = self.handle.expect( [ self.prompt, self.dockerPrompt, pexpect.TIMEOUT, "Aborted at" ] )
if i == 2:
self.handle.send( "\x03" ) # ctrl-c to close switch agent
self.handle.sendline( "" )
elif i == 1:
self.handle.sendline( "exit" ) # exit docker
self.handle.expect( self.prompt )
elif i == 0:
self.handle.sendline( "docker stop stratum" ) # Make sure the container is stopped
self.handle.expect( self.prompt )
main.log.debug( self.name + ": Stratum Switch agent stopped" )
return
elif i == 3:
main.log.error( "Stratum agent aborted" )
# TODO: Find and save any extra logs
output = self.handle.before + self.handle.after
self.handle.sendline( "" )
self.handle.expect( self.prompt )
output += self.handle.before + self.handle.after
main.log.debug( output )
main.cleanAndExit()
except pexpect.TIMEOUT:
main.log.error( self.name + ": pexpect.TIMEOUT found" )
main.log.debug( self.handle.before )
return main.FALSE
except pexpect.EOF:
main.log.error( self.name + ": EOF exception found" )
main.log.error( self.name + ": " + self.handle.before )
main.cleanAndExit()
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()