[ONOS-7356] Decouple Scapy from TestON tests
- Create MininetScapyCliDriver for mininet based scapy tests
- Move scapy related setup to a single test case in FUNCflow and
FUNCgroup
Change-Id: I02e628b1fda6e6f6f7cafde420749ddda88e898f
diff --git a/TestON/drivers/common/cli/emulator/mininetscapyclidriver.py b/TestON/drivers/common/cli/emulator/mininetscapyclidriver.py
new file mode 100644
index 0000000..4874c02
--- /dev/null
+++ b/TestON/drivers/common/cli/emulator/mininetscapyclidriver.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+"""
+2015-2016
+Copyright 2016 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/>.
+
+MininetScapyCliDriver is for controlling scapy hosts running in Mininet
+
+TODO: Add Explanation on how to install scapy
+"""
+import pexpect
+import re
+import sys
+import types
+import os
+from drivers.common.cli.emulator.scapyclidriver import ScapyCliDriver
+
+
+class MininetScapyCliDriver( ScapyCliDriver ):
+ """
+ MininetScapyCliDriver is for controlling scapy hosts running in Mininet
+ """
+ def __init__( self ):
+ super( MininetScapyCliDriver, self ).__init__()
+ self.handle = self
+ self.name = None
+ self.home = None
+ self.wrapped = sys.modules[ __name__ ]
+ self.flag = 0
+ self.hostPrompt = "~#"
+ self.scapyPrompt = ">>>"
+
+ def connect( self, **connectargs ):
+ """
+ Here the main is the TestON instance after creating
+ all the log handles.
+ """
+ try:
+ for key in connectargs:
+ vars( self )[ key ] = connectargs[ key ]
+ self.home = self.options[ 'home' ] if 'home' in self.options.keys() else "~/mininet"
+ self.name = self.options[ 'name' ]
+ self.ifaceName = self.options[ 'ifaceName' ] if 'ifaceName' in self.options.keys() else self.name + "-eth0"
+
+ try:
+ if os.getenv( str( self.ip_address ) ) is not None:
+ self.ip_address = os.getenv( str( self.ip_address ) )
+ else:
+ main.log.info( self.name +
+ ": Trying to connect to " +
+ self.ip_address )
+
+ 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(
+ ScapyCliDriver,
+ self ).connect(
+ user_name=self.user_name,
+ ip_address=self.ip_address,
+ port=None,
+ pwd=self.pwd )
+
+ if self.handle:
+ main.log.info( "Connection successful to the host " +
+ self.user_name +
+ "@" +
+ self.ip_address )
+ return main.TRUE
+ else:
+ main.log.error( "Connection failed to the host " +
+ self.user_name +
+ "@" +
+ self.ip_address )
+ main.log.error( "Failed to connect to the Mininet Host" )
+ 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 disconnect( self ):
+ """
+ Called at the end of the test to stop the scapy component and
+ disconnect the handle.
+ """
+ self.handle.sendline( '' )
+ i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
+ timeout=2 )
+ response = main.TRUE
+ if i == 0:
+ response = self.stopNet()
+ elif i == 1:
+ return main.TRUE
+ # print "Disconnecting Mininet"
+ if self.handle:
+ self.handle.sendline( "exit" )
+ self.handle.expect( "exit" )
+ self.handle.expect( "(.*)" )
+ else:
+ main.log.error( "Connection failed to the host" )
+ return response
+
+ def stopNet( self, fileName="", timeout=5 ):
+ """
+ Stops mininet.
+ Returns main.TRUE if the mininet successfully stops and
+ main.FALSE if the pexpect handle does not exist.
+
+ Will cleanup and exit the test if scapy fails to stop
+ """
+ main.log.info( self.name + ": Stopping scapy..." )
+ response = ''
+ if self.handle:
+ try:
+ self.handle.sendline( "" )
+ i = self.handle.expect( [ '>>>',
+ self.prompt,
+ pexpect.EOF,
+ pexpect.TIMEOUT ],
+ timeout )
+ if i == 0:
+ main.log.info( "Exiting scapy..." )
+ response = self.execute(
+ cmd="exit",
+ prompt="(.*)",
+ timeout=120 )
+ main.log.info( self.name + ": Stopped" )
+ response = main.TRUE
+
+ if i == 1:
+ main.log.info( " Mininet trying to exit while not " +
+ "in the mininet prompt" )
+ elif i == 2:
+ main.log.error( "Something went wrong exiting mininet" )
+ elif i == 3: # timeout
+ main.log.error( "Something went wrong exiting mininet " +
+ "TIMEOUT" )
+
+ if fileName:
+ self.handle.sendline( "" )
+ self.handle.expect( self.prompt )
+ self.handle.sendline(
+ "sudo kill -9 \`ps -ef | grep \"" +
+ fileName +
+ "\" | grep -v grep | awk '{print $2}'\`" )
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanAndExit()
+ else:
+ main.log.error( self.name + ": Connection failed to the host" )
+ response = main.FALSE
+ return response
+
+ def createHostComponent( self, name ):
+ """
+ Creates a new mininet cli component with the same parameters as self.
+ This new component is intended to be used to login to the hosts created
+ by mininet.
+
+ Arguments:
+ name - The string of the name of this component. The new component
+ will be assigned to main.<name> .
+ In addition, main.<name>.name = str( name )
+ """
+ try:
+ # look to see if this component already exists
+ getattr( main, name )
+ except AttributeError:
+ # namespace is clear, creating component
+ main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
+ main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
+ main.componentInit( name )
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanAndExit()
+ else:
+ # namespace is not clear!
+ main.log.error( name + " component already exists!" )
+ main.cleanAndExit()
+
+ def removeHostComponent( self, name ):
+ """
+ Remove host component
+ Arguments:
+ name - The string of the name of the component to delete.
+ """
+ try:
+ # Get host component
+ component = getattr( main, name )
+ except AttributeError:
+ main.log.error( "Component " + name + " does not exist." )
+ return main.FALSE
+ try:
+ # Disconnect from component
+ component.disconnect()
+ # Delete component
+ delattr( main, name )
+ # Delete component from ComponentDictionary
+ del( main.componentDictionary[ name ] )
+ return main.TRUE
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanAndExit()
+
+ def startHostCli( self, host=None ):
+ """
+ Use the mininet m utility to connect to the host's cli
+ """
+ # These are fields that can be used by scapy packets. Initialized to None
+ self.hostIp = None
+ self.hostMac = None
+ try:
+ if not host:
+ host = self.name
+ self.handle.sendline( self.home + "/util/m " + host )
+ self.handle.sendline( "cd" )
+ self.handle.expect( self.hostPrompt )
+ self.handle.sendline( "" )
+ self.handle.expect( self.hostPrompt )
+ return main.TRUE
+ except pexpect.TIMEOUT:
+ main.log.exception( self.name + ": Command timed out" )
+ return main.FALSE
+ except pexpect.EOF:
+ main.log.exception( self.name + ": connection closed." )
+ main.cleanAndExit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanAndExit()
+
+if __name__ != "__main__":
+ sys.modules[ __name__ ] = MininetScapyCliDriver()
diff --git a/TestON/drivers/common/cli/emulator/scapyclidriver.py b/TestON/drivers/common/cli/emulator/scapyclidriver.py
index 6ef63c4..418aa9e 100644
--- a/TestON/drivers/common/cli/emulator/scapyclidriver.py
+++ b/TestON/drivers/common/cli/emulator/scapyclidriver.py
@@ -45,8 +45,7 @@
self.wrapped = sys.modules[ __name__ ]
self.flag = 0
# TODO: Refactor driver to use these everywhere
- self.hostPrompt = "~#"
- self.bashPrompt = "\$"
+ self.hostPrompt = "\$"
self.scapyPrompt = ">>>"
def connect( self, **connectargs ):
@@ -56,15 +55,9 @@
try:
for key in connectargs:
vars( self )[ key ] = connectargs[ key ]
- self.home = "~/mininet"
+ self.home = self.options[ 'home' ] if 'home' in self.options.keys() else "~/"
self.name = self.options[ 'name' ]
- for key in self.options:
- if key == "home":
- self.home = self.options[ 'home' ]
- break
- if self.home is None or self.home == "":
- self.home = "~/mininet"
-
+ self.ifaceName = self.options[ 'ifaceName' ] if 'ifaceName' in self.options.keys() else self.name + "-eth0"
try:
if os.getenv( str( self.ip_address ) ) is not None:
self.ip_address = os.getenv( str( self.ip_address ) )
@@ -114,152 +107,19 @@
Called at the end of the test to stop the scapy component and
disconnect the handle.
"""
- self.handle.sendline( '' )
- i = self.handle.expect( [ 'mininet>', pexpect.EOF, pexpect.TIMEOUT ],
- timeout=2 )
response = main.TRUE
- if i == 0:
- response = self.stopNet()
- elif i == 1:
- return main.TRUE
- # print "Disconnecting Mininet"
- if self.handle:
- self.handle.sendline( "exit" )
- self.handle.expect( "exit" )
- self.handle.expect( "(.*)" )
- else:
- main.log.error( "Connection failed to the host" )
- return response
-
- def stopNet( self, fileName="", timeout=5 ):
- """
- Stops mininet.
- Returns main.TRUE if the mininet successfully stops and
- main.FALSE if the pexpect handle does not exist.
-
- Will cleanup and exit the test if scapy fails to stop
- """
- main.log.info( self.name + ": Stopping scapy..." )
- response = ''
- if self.handle:
- try:
- self.handle.sendline( "" )
- i = self.handle.expect( [ '>>>',
- self.prompt,
- pexpect.EOF,
- pexpect.TIMEOUT ],
- timeout )
- if i == 0:
- main.log.info( "Exiting scapy..." )
- response = self.execute(
- cmd="exit",
- prompt="(.*)",
- timeout=120 )
- main.log.info( self.name + ": Stopped" )
- response = main.TRUE
-
- if i == 1:
- main.log.info( " Mininet trying to exit while not " +
- "in the mininet prompt" )
- elif i == 2:
- main.log.error( "Something went wrong exiting mininet" )
- elif i == 3: # timeout
- main.log.error( "Something went wrong exiting mininet " +
- "TIMEOUT" )
-
- if fileName:
- self.handle.sendline( "" )
- self.handle.expect( self.prompt )
- self.handle.sendline(
- "sudo kill -9 \`ps -ef | grep \"" +
- fileName +
- "\" | grep -v grep | awk '{print $2}'\`" )
- except pexpect.EOF:
- main.log.error( self.name + ": EOF exception found" )
- main.log.error( self.name + ": " + self.handle.before )
- main.cleanAndExit()
- else:
- main.log.error( self.name + ": Connection failed to the host" )
+ try:
+ if self.handle:
+ self.handle.sendline( "exit" )
+ self.handle.expect( "closed" )
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ except Exception:
+ main.log.exception( self.name + ": Connection failed to the host" )
response = main.FALSE
return response
- def createHostComponent( self, name ):
- """
- Creates a new mininet cli component with the same parameters as self.
- This new component is intended to be used to login to the hosts created
- by mininet.
-
- Arguments:
- name - The string of the name of this component. The new component
- will be assigned to main.<name> .
- In addition, main.<name>.name = str( name )
- """
- try:
- # look to see if this component already exists
- getattr( main, name )
- except AttributeError:
- # namespace is clear, creating component
- main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
- main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
- main.componentInit( name )
- except Exception:
- main.log.exception( self.name + ": Uncaught exception!" )
- main.cleanAndExit()
- else:
- # namespace is not clear!
- main.log.error( name + " component already exists!" )
- main.cleanAndExit()
-
- def removeHostComponent( self, name ):
- """
- Remove host component
- Arguments:
- name - The string of the name of the component to delete.
- """
- try:
- # Get host component
- component = getattr( main, name )
- except AttributeError:
- main.log.error( "Component " + name + " does not exist." )
- return main.FALSE
- try:
- # Disconnect from component
- component.disconnect()
- # Delete component
- delattr( main, name )
- # Delete component from ComponentDictionary
- del( main.componentDictionary[ name ] )
- return main.TRUE
- except Exception:
- main.log.exception( self.name + ": Uncaught exception!" )
- main.cleanAndExit()
-
- def startHostCli( self, host=None ):
- """
- Use the mininet m utility to connect to the host's cli
- """
- # These are fields that can be used by scapy packets. Initialized to None
- self.hostIp = None
- self.hostMac = None
- try:
- if not host:
- host = self.name
- self.handle.sendline( self.home + "/util/m " + host )
- self.handle.sendline( "cd" )
- self.handle.expect( self.hostPrompt )
- self.handle.sendline( "" )
- self.handle.expect( self.hostPrompt )
- return main.TRUE
- except pexpect.TIMEOUT:
- main.log.exception( self.name + ": Command timed out" )
- return main.FALSE
- except pexpect.EOF:
- main.log.exception( self.name + ": connection closed." )
- main.cleanAndExit()
- except Exception:
- main.log.exception( self.name + ": Uncaught exception!" )
- main.cleanAndExit()
-
def startScapy( self, mplsPath="" ):
"""
Start the Scapy cli
@@ -847,7 +707,7 @@
Options:
ifaceName - the name of the interface to listen on. If none is given,
- defaults to <host name>-eth0
+ defaults to self.ifaceName which is <host name>-eth0
pktFilter - A string in Berkeley Packet Filter (BPF) format which
specifies which packets to sniff
sniffCount - The number of matching packets to capture before returning
@@ -856,7 +716,7 @@
"""
try:
# TODO: add all params, or use kwargs
- ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
+ ifaceName = str( ifaceName ) if ifaceName else self.ifaceName
# Set interface
self.handle.sendline( ' conf.iface = "' + ifaceName + '"' )
self.handle.expect( self.scapyPrompt )
@@ -946,7 +806,7 @@
Save host's MAC address
"""
try:
- ifaceName = str( ifaceName ) if ifaceName else self.name + "-eth0"
+ ifaceName = str( ifaceName ) if ifaceName else self.ifaceName
cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
self.handle.sendline( cmd )
self.handle.expect( self.scapyPrompt )