blob: 6b4346cc804971503a585eeb254769a4df83d934 [file] [log] [blame]
"""
Copyright 2015 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/>.
Wrapper functions for FuncIntent
This functions include Onosclidriver and Mininetclidriver driver functions
Author: kelvin@onlab.us
"""
import time
import copy
import json
import types
def __init__( self ):
self.default = ''
def installHostIntent( main,
name,
host1,
host2,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="" ):
"""
Installs a Host Intent
Description:
Install a host intent using
add-host-intent
Steps:
- Fetch host data if not given
- Add host intent
- Ingress device is the first sender host
- Egress devices are the recipient devices
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
host1 - Dictionary for host1
{ "name":"h8", "id":"of:0000000000000005/8" }
host2 - Dictionary for host2
{ "name":"h16", "id":"of:0000000000000006/8" }
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
"""
assert main, "There is no main variable"
assert host1, "You must specify host1"
assert host2, "You must specify host2"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding single point to multi point intents" )
try:
if not host1.get( "id" ):
main.log.warn( "ID not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
main.log.debug( main.hostsData.get( host1.get( "name" ) ) )
host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "id" )
if not host2.get( "id" ):
main.log.warn( "ID not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "id" )
vlanId = host1.get( "vlanId" )
# Adding host intents
main.log.info( itemName + ": Adding host intents" )
intent1 = main.Cluster.active( onosNode ).REST.addHostIntent( hostIdOne=host1.get( "id" ),
hostIdTwo=host2.get( "id" ),
vlanId=vlanId )
# Get all intents ID in the system, time delay right after intents are added
time.sleep( main.addIntentSleep )
intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentsId:
errorMsg += " There was a problem installing host to host intent."
main.log.error( errorMsg )
return main.FALSE
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, intentsId ), sleep=main.checkIntentSleep, attempts=5 ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentsId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Host Intent did not install correctly" )
main.assertReturnString += 'Install Intent State Failed\n'
return main.FALSE
def testHostIntent( main,
name,
intentId,
host1,
host2,
onosNode=0,
sw1="s5",
sw2="s2",
expectedLink=0 ):
"""
Test a Host Intent
Description:
Test a host intent of given ID between given hosts
Steps:
- Fetch host data if not given
- Check Intent State
- Check Flow State
- Check Connectivity
- Check Lack of Connectivity Between Hosts not in the Intent
- Reroute
- Take Expected Link Down
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Bring Expected Link Up
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Remove Topology
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
intentId - intent ID to be tested ( and removed )
host1 - Dictionary for host1
{ "name":"h8", "id":"of:0000000000000005/8" }
host2 - Dictionary for host2
{ "name":"h16", "id":"of:0000000000000006/8" }
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
# Parameter Validity Check
assert main, "There is no main variable"
assert host1, "You must specify host1"
assert host2, "You must specify host2"
global itemName
itemName = name
tempHostsData = {}
onosNode = int( onosNode )
main.log.info( itemName + ": Testing Host Intent" )
try:
if not host1.get( "id" ):
main.log.warn( "Id not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "location" )
if not host2.get( "id" ):
main.log.warn( "Id not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "location" )
senderNames = [ host1.get( "name" ), host2.get( "name" ) ]
recipientNames = [ host1.get( "name" ), host2.get( "name" ) ]
vlanId = host1.get( "vlanId" )
except( KeyError, TypeError ):
main.log.error( "There was a problem loading the hosts data." )
return main.FALSE
testResult = main.TRUE
main.log.info( itemName + ": Adding single point to multi point intents" )
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Initial Intent State Passed\n'
else:
main.assertReturnString += 'Initial Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Initial Flow State Passed\n'
else:
main.assertReturnString += 'Intial Flow State Failed\n'
testResult = main.FALSE
# Check Connectivity
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Initial Ping Passed\n'
else:
main.assertReturnString += 'Initial Ping Failed\n'
testResult = main.FALSE
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# Take link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Down Flow State Passed\n'
else:
main.assertReturnString += 'Link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ), sleep=10 ):
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Link Down Pingall Passed\n'
else:
main.assertReturnString += 'Link Down Pingall Failed\n'
testResult = main.FALSE
# Bring link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Wait for reroute
time.sleep( main.rerouteSleep )
# Check Intents
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Up Intent State Passed\n'
else:
main.assertReturnString += 'Link Up Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Up Flow State Passed\n'
else:
main.assertReturnString += 'Link Up Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Link Up Pingall Passed\n'
else:
main.assertReturnString += 'Link Up Pingall Failed\n'
testResult = main.FALSE
# Remove all intents
if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, ) ):
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
testResult = main.FALSE
return testResult
def installPointIntent( main,
name,
senders,
recipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
protected=False,
ipProto="",
ipSrc="",
ipDst="",
tcpSrc="",
tcpDst="" ):
"""
Installs a Single to Single Point Intent
Description:
Install a single to single point intent
Steps:
- Fetch host data if not given
- Add point intent
- Ingress device is the first sender device
- Egress device is the first recipient device
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
[ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
recipients - List of host dictionaries i.e.
[ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
# Assert devices or main.hostsData, "You must specify devices"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding single to single point intents" )
try:
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
vlanId = senders[ 0 ].get( "vlanId" )
ingressDevice = senders[ 0 ].get( "device" )
egressDevice = recipients[ 0 ].get( "device" )
portIngress = senders[ 0 ].get( "port", "" )
portEgress = recipients[ 0 ].get( "port", "" )
main.log.debug( ingressDevice )
main.log.debug( egressDevice )
srcMac = senders[ 0 ].get( "mac" )
dstMac = recipients[ 0 ].get( "mac" )
ipSrc = senders[ 0 ].get( "ip" )
ipDst = recipients[ 0 ].get( "ip" )
intent1 = main.Cluster.active( onosNode ).REST.addPointIntent(
ingressDevice=ingressDevice,
egressDevice=egressDevice,
ingressPort=portIngress,
egressPort=portEgress,
ethType=ethType,
ethSrc=srcMac,
ethDst=dstMac,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
protected=protected,
ipProto=ipProto,
ipSrc=ipSrc,
ipDst=ipDst,
tcpSrc=tcpSrc,
tcpDst=tcpDst,
vlanId=vlanId )
time.sleep( main.addIntentSleep )
intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentsId:
errorMsg += " There was a problem installing Point to Point intent."
main.log.error( errorMsg )
return main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, intentsId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentsId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Host Intent did not install correctly" )
main.assertReturnString += 'Install Intent State Failed\n'
return main.FALSE
def testPointIntent( main,
name,
intentId,
senders,
recipients,
badSenders={},
badRecipients={},
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
protected=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="s5",
sw2="s2",
expectedLink=0,
useTCP=False ):
"""
Test a Point Intent
Description:
Test a point intent
Steps:
- Fetch host data if not given
- Check Intent State
- Check Flow State
- Check Connectivity
- Check Lack of Connectivity Between Hosts not in the Intent
- Reroute
- Take Expected Link Down
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Bring Expected Link Up
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Remove Topology
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
{ "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
recipients - List of host dictionaries i.e.
{ "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
# Parameter Validity Check
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
global itemName
itemName = name
tempHostsData = {}
onosNode = int( onosNode )
main.log.info( itemName + ": Testing Point Intent" )
try:
# Names for scapy
senderNames = [ x.get( "name" ) for x in senders ]
recipientNames = [ x.get( "name" ) for x in recipients ]
badSenderNames = [ x.get( "name" ) for x in badSenders ]
badRecipientNames = [ x.get( "name" ) for x in badRecipients ]
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
vlanId = senders[ 0 ].get( "vlanId" )
except( KeyError, TypeError ):
main.log.error( "There was a problem loading the hosts data." )
return main.FALSE
testResult = main.TRUE
main.log.info( itemName + ": Testing point intents" )
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Initial Intent State Passed\n'
else:
main.assertReturnString += 'Initial Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Initial Flow State Passed\n'
else:
main.assertReturnString += 'Intial Flow State Failed\n'
testResult = main.FALSE
# Check Connectivity
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Initial Ping Passed\n'
else:
main.assertReturnString += 'Initial Ping Failed\n'
testResult = main.FALSE
# Check connections that shouldn't work
if badSenderNames:
main.log.info( "Checking that packets from incorrect sender do not go through" )
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, badSenderNames, recipientNames ), kwargs={ "expectFailure": True } ):
main.assertReturnString += 'Bad Sender Ping Passed\n'
else:
main.assertReturnString += 'Bad Sender Ping Failed\n'
testResult = main.FALSE
if badRecipientNames:
main.log.info( "Checking that packets to incorrect recipients do not go through" )
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, badRecipientNames ), kwargs={ "expectFailure": True } ):
main.assertReturnString += 'Bad Recipient Ping Passed\n'
else:
main.assertReturnString += 'Bad Recipient Ping Failed\n'
testResult = main.FALSE
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# Take link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
if protected:
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Link down Scapy Packet Received Passed\n'
else:
main.assertReturnString += 'Link down Scapy Packet Recieved Failed\n'
testResult = main.FALSE
if ProtectedIntentCheck( main ):
main.assertReturnString += 'Protected Intent Check Passed\n'
else:
main.assertReturnString += 'Protected Intent Check Failed\n'
testResult = main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Down Flow State Passed\n'
else:
main.assertReturnString += 'Link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ), sleep=10 ):
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Link Down Pingall Passed\n'
else:
main.assertReturnString += 'Link Down Pingall Failed\n'
testResult = main.FALSE
# Bring link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Wait for reroute
time.sleep( main.rerouteSleep )
# Check Intents
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentId ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Up Intent State Passed\n'
else:
main.assertReturnString += 'Link Up Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Up Flow State Passed\n'
else:
main.assertReturnString += 'Link Up Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
else:
main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
testResult = main.FALSE
# Remove all intents
if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, ) ):
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
testResult = main.FALSE
return testResult
def pointIntentTcp( main,
name,
host1,
host2,
onosNode=0,
deviceId1="",
deviceId2="",
port1="",
port2="",
ethType="",
mac1="",
mac2="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ip1="",
ip2="",
tcp1="",
tcp2="",
sw1="",
sw2="",
expectedLink=0 ):
"""
Description:
Verify add-point-intent only for TCP
Steps:
- Get device ids | ports
- Add point intents
- Check intents
- Verify flows
- Ping hosts
- Reroute
- Link down
- Verify flows
- Check topology
- Ping hosts
- Link up
- Verify flows
- Check topology
- Ping hosts
- Remove intents
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
host1 - Name of first host
host2 - Name of second host
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
deviceId1 - ONOS device id of the first switch, the same as the
location of the first host eg. of:0000000000000001/1,
located at device 1 port 1
deviceId2 - ONOS device id of the second switch
port1 - The port number where the first host is attached
port2 - The port number where the second host is attached
ethType - Ethernet type eg. IPV4, IPV6
mac1 - Mac address of first host
mac2 - Mac address of the second host
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
ip1 - IP address of first host
ip2 - IP address of second host
tcp1 - TCP port of first host
tcp2 - TCP port of second host
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert name, "variable name is empty"
assert host1 and host2, "You must specify hosts"
global itemName
itemName = name
host1 = host1
host2 = host2
hostNames = [ host1, host2 ]
intentsId = []
iperfResult = main.TRUE
intentResult = main.TRUE
removeIntentResult = main.TRUE
flowResult = main.TRUE
topoResult = main.TRUE
linkDownResult = main.TRUE
linkUpResult = main.TRUE
onosNode = int( onosNode )
# Adding bidirectional point intents
main.log.info( itemName + ": Adding point intents" )
ctrl = main.Cluster.active( onosNode )
intent1 = ctrl.REST.addPointIntent( ingressDevice=deviceId1,
egressDevice=deviceId2,
ingressPort=port1,
egressPort=port2,
ethType=ethType,
ethSrc=mac1,
ethDst=mac2,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip1,
ipDst=ip2,
tcpSrc=tcp1,
tcpDst="" )
intent2 = ctrl.REST.addPointIntent( ingressDevice=deviceId2,
egressDevice=deviceId1,
ingressPort=port2,
egressPort=port1,
ethType=ethType,
ethSrc=mac2,
ethDst=mac1,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip2,
ipDst=ip1,
tcpSrc=tcp2,
tcpDst="" )
intent3 = ctrl.REST.addPointIntent( ingressDevice=deviceId1,
egressDevice=deviceId2,
ingressPort=port1,
egressPort=port2,
ethType=ethType,
ethSrc=mac1,
ethDst=mac2,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip1,
ipDst=ip2,
tcpSrc="",
tcpDst=tcp2 )
intent4 = ctrl.REST.addPointIntent( ingressDevice=deviceId2,
egressDevice=deviceId1,
ingressPort=port2,
egressPort=port1,
ethType=ethType,
ethSrc=mac2,
ethDst=mac1,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip2,
ipDst=ip1,
tcpSrc="",
tcpDst=tcp1 )
# Get all intents ID in the system, time delay right after intents are added
time.sleep( main.addIntentSleep )
intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
# Check intents state
time.sleep( main.checkIntentSleep )
intentResult = checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Check intents state again if first check fails...
if not intentResult:
intentResult = checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Run iperf to both host
iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
host2, 10 )
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# link down
linkDownResult = link( main, sw1, sw2, "down" )
intentResult = intentResult and checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, expectedLink )
# Run iperf to both host
iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
host2, 10 )
intentResult = checkIntentState( main, intentsId )
# Checks ONOS state in link down
if linkDownResult and topoResult and iperfResult and intentResult:
main.log.info( itemName + ": Successfully brought link down" )
else:
main.log.error( itemName + ": Failed to bring link down" )
# link up
linkUpResult = link( main, sw1, sw2, "up" )
time.sleep( main.rerouteSleep )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, main.numLinks )
# Run iperf to both host
iperfResult = iperfResult and main.Mininet1.iperftcp( host1,
host2, 10 )
intentResult = checkIntentState( main, intentsId )
# Checks ONOS state in link up
if linkUpResult and topoResult and iperfResult and intentResult:
main.log.info( itemName + ": Successfully brought link back up" )
else:
main.log.error( itemName + ": Failed to bring link back up" )
# Remove all intents
removeIntentResult = removeAllIntents( main )
stepResult = iperfResult and linkDownResult and linkUpResult \
and intentResult and removeIntentResult
return stepResult
def installSingleToMultiIntent( main,
name,
senders,
recipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
partial=False ):
"""
Verify Single to Multi Point intents
NOTE:If main.hostsData is not defined, variables data should be passed
in the same order index wise. All devices in the list should have the
same format, either all the devices have its port or it doesn't.
eg. hostName = [ 'h1', 'h2' ,.. ]
devices = [ 'of:0000000000000001', 'of:0000000000000002', ... ]
ports = [ '1', '1', .. ]
...
Description:
Verify add-single-to-multi-intent iterates through the list of given
host | devices and add intents
Steps:
- Get device ids | ports
- Add single to multi point intents
- Check intents
- Verify flows
- Ping hosts
- Reroute
- Link down
- Verify flows
- Check topology
- Ping hosts
- Link up
- Verify flows
- Check topology
- Ping hosts
- Remove intents
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
hostNames - List of host names
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
devices - List of device ids in the same order as the hosts
in hostNames
ports - List of port numbers in the same order as the device in
devices
ethType - Ethernet type eg. IPV4, IPV6
macs - List of hosts mac address in the same order as the hosts in
hostNames
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
ipAddresses - IP addresses of host in the same order as the hosts in
hostNames
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
# Assert devices or main.hostsData, "You must specify devices"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding single point to multi point intents" )
try:
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
vlanId = senders[ 0 ].get( "vlanId" )
ingressDevice = senders[ 0 ].get( "device" )
egressDeviceList = [ x.get( "device" ) for x in recipients if x.get( "device" ) ]
portIngress = senders[ 0 ].get( "port", "" )
portEgressList = [ x.get( "port" ) for x in recipients if x.get( "port" ) ]
if not portEgressList:
portEgressList = []
main.log.debug( ingressDevice )
main.log.debug( egressDeviceList )
srcMac = senders[ 0 ].get( "mac" )
dstMac = []
for r in recipients:
mac = r.get( "mac" )
dstMac.append( mac )
ipSrc = senders[ 0 ].get( "ip" )
ipDst = []
for r in recipients:
ip = r.get( "ip" )
ipDst.append( ip )
# Adding point intent
intentId = main.Cluster.active( onosNode ).REST.addSinglepointToMultipointIntent(
ingressDevice=ingressDevice,
egressDeviceList=egressDeviceList,
portIngress=portIngress,
portEgressList=portEgressList,
ethType=ethType,
ethSrc=srcMac,
# ethDst=dstMac, #Isn't working because of ONOS itself
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ipSrc,
ipDst=ipDst,
tcpSrc="",
tcpDst="",
vlanId=vlanId,
partial=partial )
time.sleep( main.addIntentSleep )
intentsId = main.Cluster.active( 0 ).REST.getIntentsId()
except ( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentId:
errorMsg += " There was a problem installing Singlepoint to Multipoint intent."
main.log.error( errorMsg )
return main.FALSE
# Check intents state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, intentsId ), sleep=main.checkIntentSleep ):
return intentsId
else:
main.log.error( "Single to Multi Intent did not install correctly" )
return main.FALSE
def multiToSingleIntent( main,
name,
hostNames,
onosNode=0,
devices="",
ports=None,
ethType="",
macs=None,
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
expectedLink=0 ):
"""
Verify Single to Multi Point intents
NOTE:If main.hostsData is not defined, variables data should be passed in the
same order index wise. All devices in the list should have the same
format, either all the devices have its port or it doesn't.
eg. hostName = [ 'h1', 'h2' ,.. ]
devices = [ 'of:0000000000000001', 'of:0000000000000002', ... ]
ports = [ '1', '1', .. ]
...
Description:
Verify add-multi-to-single-intent
Steps:
- Get device ids | ports
- Add multi to single point intents
- Check intents
- Verify flows
- Ping hosts
- Reroute
- Link down
- Verify flows
- Check topology
- Ping hosts
- Link up
- Verify flows
- Check topology
- Ping hosts
- Remove intents
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
hostNames - List of host names
Optional:
onosNode - ONOS node to install the intents in main.RESTs[ ]
0 by default so that it will always use the first
ONOS node
devices - List of device ids in the same order as the hosts
in hostNames
ports - List of port numbers in the same order as the device in
devices
ethType - Ethernet type eg. IPV4, IPV6
macs - List of hosts mac address in the same order as the hosts in
hostNames
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
ipAddresses - IP addresses of host in the same order as the hosts in
hostNames
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert hostNames, "You must specify hosts"
assert devices or main.hostsData, "You must specify devices"
global itemName
itemName = name
tempHostsData = {}
intentsId = []
onosNode = int( onosNode )
macsDict = {}
ipDict = {}
if hostNames and devices:
if len( hostNames ) != len( devices ):
main.log.debug( "hosts and devices does not have the same length" )
# print "len hostNames = ", len( hostNames )
# print "len devices = ", len( devices )
return main.FALSE
if ports:
if len( ports ) != len( devices ):
main.log.error( "Ports and devices does " +
"not have the same length" )
# print "len devices = ", len( devices )
# print "len ports = ", len( ports )
return main.FALSE
else:
main.log.info( "Device Ports are not specified" )
if macs:
for i in range( len( devices ) ):
macsDict[ devices[ i ] ] = macs[ i ]
elif hostNames and not devices and main.hostsData:
devices = []
main.log.info( "multiToSingleIntent function is using main.hostsData" )
for host in hostNames:
devices.append( main.hostsData.get( host ).get( 'location' ) )
macsDict[ main.hostsData.get( host ).get( 'location' ) ] = \
main.hostsData.get( host ).get( 'mac' )
ipDict[ main.hostsData.get( host ).get( 'location' ) ] = \
main.hostsData.get( host ).get( 'ipAddresses' )
# print main.hostsData
# print 'host names = ', hostNames
# print 'devices = ', devices
# print "macsDict = ", macsDict
pingResult = main.TRUE
intentResult = main.TRUE
removeIntentResult = main.TRUE
flowResult = main.TRUE
topoResult = main.TRUE
linkDownResult = main.TRUE
linkUpResult = main.TRUE
devicesCopy = copy.copy( devices )
if ports:
portsCopy = copy.copy( ports )
main.log.info( itemName + ": Adding multi point to single point intents" )
# Check flows count in each node
checkFlowsCount( main )
# Adding bidirectional point intents
for i in range( len( devices ) ):
egressDevice = devicesCopy[ i ]
ingressDeviceList = copy.copy( devicesCopy )
ingressDeviceList.remove( egressDevice )
if ports:
portEgress = portsCopy[ i ]
portIngressList = copy.copy( portsCopy )
del portIngressList[ i ]
else:
portEgress = ""
portIngressList = None
if not macsDict:
dstMac = ""
else:
dstMac = macsDict[ egressDevice ]
if dstMac is None:
main.log.debug( "There is no MAC in device - " + egressDevice )
dstMac = ""
intentsId.append(
main.Cluster.active( onosNode ).REST.addMultipointToSinglepointIntent(
ingressDeviceList=ingressDeviceList,
egressDevice=egressDevice,
portIngressList=portIngressList,
portEgress=portEgress,
ethType=ethType,
ethDst=dstMac,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc="",
ipDst="",
tcpSrc="",
tcpDst="" ) )
pingResult = pingallHosts( main, hostNames )
# Check intents state
time.sleep( main.checkIntentSleep )
intentResult = checkIntentState( main, intentsId )
# Check intents state again if first check fails...
if not intentResult:
intentResult = checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Ping hosts
pingResult = pingResult and pingallHosts( main, hostNames )
# Ping hosts again...
pingResult = pingResult and pingallHosts( main, hostNames )
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# link down
linkDownResult = link( main, sw1, sw2, "down" )
intentResult = intentResult and checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, expectedLink )
# Ping hosts
pingResult = pingResult and pingallHosts( main, hostNames )
intentResult = checkIntentState( main, intentsId )
# Checks ONOS state in link down
if linkDownResult and topoResult and pingResult and intentResult:
main.log.info( itemName + ": Successfully brought link down" )
else:
main.log.error( itemName + ": Failed to bring link down" )
# link up
linkUpResult = link( main, sw1, sw2, "up" )
time.sleep( main.rerouteSleep )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, main.numLinks )
# Ping hosts
pingResult = pingResult and pingallHosts( main, hostNames )
intentResult = checkIntentState( main, intentsId )
# Checks ONOS state in link up
if linkUpResult and topoResult and pingResult and intentResult:
main.log.info( itemName + ": Successfully brought link back up" )
else:
main.log.error( itemName + ": Failed to bring link back up" )
# Remove all intents
removeIntentResult = removeAllIntents( main, intentsId )
stepResult = pingResult and linkDownResult and linkUpResult \
and intentResult and removeIntentResult
return stepResult
def pingallHosts( main, hostList ):
# Ping all host in the hosts list variable
print "Pinging : ", hostList
pingResult = main.TRUE
pingResult = main.Mininet1.pingallHosts( hostList )
return pingResult
def getHostsData( main, hostList ):
"""
Use fwd app and pingall to discover all the hosts
"""
activateResult = main.TRUE
appCheck = main.TRUE
getDataResult = main.TRUE
main.log.info( "Activating reactive forwarding app " )
activateResult = main.Cluster.active( 0 ).activateApp( "org.onosproject.fwd" )
if not activateResult:
main.log.error( "Something went wrong installing fwd app" )
time.sleep( main.fwdSleep )
if isinstance( hostList[ 0 ], types.StringType ):
main.Mininet1.pingallHosts( hostList )
elif isinstance( hostList[ 0 ], types.ListType ):
for i in xrange( len( hostList ) ):
main.Mininet1.pingallHosts( hostList[ i ] )
hostsJson = json.loads( main.Cluster.active( 0 ).REST.hosts() )
hosts = main.Mininet1.getHosts().keys()
# TODO: Make better use of new getHosts function
for host in hosts:
main.hostsData[ host ] = {}
main.hostsData[ host ][ 'mac' ] = \
main.Mininet1.getMacAddress( host ).upper()
for hostj in hostsJson:
if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
main.hostsData[ host ][ 'location' ] = \
hostj[ 'locations' ][ 0 ][ 'elementId' ] + '/' + \
hostj[ 'locations' ][ 0 ][ 'port' ]
main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
main.log.info( "Deactivating reactive forwarding app " )
deactivateResult = main.Cluster.active( 0 ).REST.deactivateApp( "org.onosproject.fwd" )
if activateResult and deactivateResult and main.hostsData:
main.log.info( "Successfully used fwd app to discover hosts " )
getDataResult = main.TRUE
else:
main.log.info( "Failed to use fwd app to discover hosts " )
getDataResult = main.FALSE
print main.hostsData
return getDataResult
def checkTopology( main, expectedLink ):
# Check onos topology
main.log.info( itemName + ": Checking ONOS topology " )
statusResult = main.Cluster.command( "checkStatus",
args=[ main.numSwitch, expectedLink ],
returnBool=True, specificDriver=3 )
if not statusResult:
main.log.error( itemName + ": Topology mismatch" )
else:
main.log.info( itemName + ": Topology match" )
return statusResult
def checkIntentState( main, intentsId ):
"""
This function will check intent state to make sure all the intents
are in INSTALLED state
"""
intentResult = main.TRUE
results = []
main.log.info( itemName + ": Checking intents state" )
# First check of intents
stateCheckResults = main.Cluster.command( "checkIntentState",
kwargs={ "intentsId": intentsId },
returnBool=True, specificDriver=3 )
expectedState = [ 'INSTALLED', 'INSTALLING' ]
if stateCheckResults:
main.log.info( itemName + ": Intents are installed correctly" )
else:
# Wait for at least 5 second before checking the intents again
main.log.error( "Intents are not installed correctly. Waiting 5 sec" )
time.sleep( 5 )
results = []
# Second check of intents since some of the intents may be in
# INSTALLING state, they should be in INSTALLED at this time
stateCheckResults = main.Cluster.command( "checkIntentState",
kwargs={ "intentsId": intentsId },
returnBool=True, specificDriver=3 )
if stateCheckResults:
main.log.info( itemName + ": Intents are installed correctly" )
intentResult = main.TRUE
else:
main.log.error( itemName + ": Intents are NOT installed correctly" )
intentResult = main.FALSE
return intentResult
def checkFlowsState( main ):
main.log.info( itemName + ": Check flows state" )
checkFlowsResult = main.Cluster.active( 0 ).REST.checkFlowsState()
return checkFlowsResult
def link( main, sw1, sw2, option ):
# link down
main.log.info( itemName + ": Bring link " + option + "between " +
sw1 + " and " + sw2 )
linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
return linkResult
def removeAllIntents( main ):
"""
Remove all intents in the intentsId
"""
onosSummary = []
removeIntentResult = main.TRUE
# Remove intents
removeIntentResult = main.Cluster.active( 0 ).REST.removeAllIntents()
if removeIntentResult:
main.log.info( itemName + ": There are no more intents remaining, " +
"successfully removed all the intents." )
return removeIntentResult
def checkFlowsCount( main ):
"""
Check flows count in each node
"""
flowsCount = []
main.log.info( itemName + ": Checking flows count in each ONOS node" )
for ctrl in main.Cluster.active():
flowsCount.append( len( json.loads( ctrl.REST.flows() ) ) )
if flowsCount:
if all( flows == flowsCount[ 0 ] for flows in flowsCount ):
main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
" flows in all ONOS node" )
else:
for i in range( main.Cluster.numCtrls ):
main.log.debug( itemName + ": " + main.Cluster.active( i ).name +
" has " + str( flowsCount[ i ] ) + " flows" )
else:
main.log.error( "Checking flows count failed, check summary command" )
return main.FALSE
return main.TRUE
def sendDiscoveryArp( main, hosts=None ):
"""
Sends Discovery ARP packets from each host provided
Defaults to each host in main.scapyHosts
"""
# Send an arp ping from each host
if not hosts:
hosts = main.scapyHosts
for host in hosts:
pkt = 'Ether( src="{0}")/ARP( psrc="{1}")'.format( host.hostMac, host.hostIp )
# Send from the VLAN interface if there is one so ONOS discovers the VLAN correctly
iface = None
for interface in host.getIfList():
if '.' in interface:
main.log.debug( "Detected VLAN interface {0}. Sending ARP packet from {0}".format( interface ) )
iface = interface
break
host.sendPacket( packet=pkt, iface=iface )
main.log.info( "Sending ARP packet from {0}".format( host.name ) )
def confirmHostDiscovery( main ):
"""
Confirms that all ONOS nodes have discovered all scapy hosts
"""
import collections
scapyHostCount = len( main.scapyHosts )
try:
from tests.dependencies.topology import Topology
except Exception:
main.log.error( "Topology not found exiting the test" )
main.cleanAndExit()
try:
main.topoRelated
except ( NameError, AttributeError ):
main.topoRelated = Topology()
hosts = main.topoRelated.getAll( "hosts", False ) # Get host data from each ONOS node
hostFails = [] # Reset for each failed attempt
# Check for matching hosts on each node
scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
for controller in range( main.Cluster.numCtrls ):
controllerStr = str( controller + 1 ) # ONOS node number
# Compare Hosts
# Load hosts data for controller node
try:
if hosts[ controller ]:
main.log.info( "Hosts discovered" )
else:
main.log.error( "Problem discovering hosts" )
if hosts[ controller ] and "Error" not in hosts[ controller ]:
try:
hostData = json.loads( hosts[ controller ] )
except ( TypeError, ValueError ):
main.log.error( "Could not load json:" + str( hosts[ controller ] ) )
hostFails.append( controllerStr )
else:
onosHostIPs = [ x.get( "ipAddresses" )[ 0 ]
for x in hostData
if len( x.get( "ipAddresses" ) ) > 0 ]
if not set( collections.Counter( scapyHostIPs ) ).issubset( set( collections.Counter( onosHostIPs ) ) ):
main.log.warn( "Controller {0} only sees nodes with {1} IPs. It should see all of the following: {2}".format( controllerStr, onosHostIPs, scapyHostIPs ) )
hostFails.append( controllerStr )
else:
main.log.error( "Hosts returned nothing or an error." )
hostFails.append( controllerStr )
except IndexError:
main.log.error( "Hosts returned nothing, Failed to discover hosts." )
return main.FALSE
if hostFails:
main.log.error( "List of failed ONOS Nodes:" + ', '.join( map( str, hostFails ) ) )
return main.FALSE
else:
return main.TRUE
def populateHostData( main ):
"""
Populates hostsData
"""
import json
try:
hostsJson = json.loads( main.Cluster.active( 0 ).REST.hosts() )
hosts = main.Mininet1.getHosts().keys()
# TODO: Make better use of new getHosts function
for host in hosts:
main.hostsData[ host ] = {}
main.hostsData[ host ][ 'mac' ] = \
main.Mininet1.getMacAddress( host ).upper()
for hostj in hostsJson:
if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
main.hostsData[ host ][ 'location' ] = \
hostj[ 'locations' ][ 0 ][ 'elementId' ] + '/' + \
hostj[ 'locations' ][ 0 ][ 'port' ]
main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
return main.TRUE
except ValueError:
main.log.error( "ValueError while populating hostsData" )
return main.FALSE
except KeyError:
main.log.error( "KeyError while populating hostsData" )
return main.FALSE
except IndexError:
main.log.error( "IndexError while populating hostsData" )
return main.FALSE
except TypeError:
main.log.error( "TypeError while populating hostsData" )
return main.FALSE
def scapyCheckConnection( main, senders, recipients, vlanId=None, useTCP=False, packet=None, packetFilter=None, expectFailure=False ):
"""
Checks the connectivity between all given sender hosts and all given recipient hosts
Packet may be specified. Defaults to Ether/IP packet
Packet Filter may be specified. Defaults to Ether/IP from current sender MAC
Todo: Optional packet and packet filter attributes for sender and recipients
Expect Failure when the sender and recipient are not supposed to have connectivity
Timeout of 1 second, returns main.TRUE if the filter is not triggered and kills the filter
"""
connectionsFunctional = main.TRUE
if not packetFilter:
packetFilter = 'ether host {}'
if useTCP:
packetFilter += ' ip proto \\tcp tcp port {}'.format( main.params[ 'SDNIP' ][ 'dstPort' ] )
if expectFailure:
timeout = 1
else:
timeout = 10
for sender in senders:
try:
senderComp = getattr( main, sender )
except AttributeError:
main.log.error( "main has no attribute {}".format( sender ) )
connectionsFunctional = main.FALSE
continue
for recipient in recipients:
# Do not send packets to self since recipient CLI will already be busy
if recipient == sender:
continue
try:
recipientComp = getattr( main, recipient )
except AttributeError:
main.log.error( "main has no attribute {}".format( recipient ) )
connectionsFunctional = main.FALSE
continue
if vlanId:
recipientComp.startFilter( pktFilter=( "vlan {}".format( vlanId ) + " && " + packetFilter.format( senderComp.hostMac ) ) )
else:
recipientComp.startFilter( pktFilter=packetFilter.format( senderComp.hostMac ) )
if not packet:
if vlanId:
pkt = 'Ether( src="{0}", dst="{2}" )/Dot1Q(vlan={4})/IP( src="{1}", dst="{3}" )'.format(
senderComp.hostMac,
senderComp.hostIp,
recipientComp.hostMac,
recipientComp.hostIp,
vlanId )
else:
pkt = 'Ether( src="{0}", dst="{2}" )/IP( src="{1}", dst="{3}" )'.format(
senderComp.hostMac,
senderComp.hostIp,
recipientComp.hostMac,
recipientComp.hostIp )
else:
pkt = packet
if vlanId:
senderComp.sendPacket( iface=( "{0}-eth0.{1}".format( sender, vlanId ) ), packet = pkt )
else:
senderComp.sendPacket( packet=pkt )
if recipientComp.checkFilter( timeout ):
if expectFailure:
main.log.error( "Packet from {0} successfully received by {1} when it should not have been".format( sender, recipient ) )
connectionsFunctional = main.FALSE
else:
main.log.info( "Packet from {0} successfully received by {1}".format( sender, recipient ) )
else:
recipientComp.killFilter()
if expectFailure:
main.log.info( "As expected, packet from {0} was not received by {1}".format( sender, recipient ) )
else:
main.log.error( "Packet from {0} was not received by {1}".format( sender, recipient ) )
connectionsFunctional = main.FALSE
return connectionsFunctional
def checkLeaderChange( leaders1, leaders2 ):
"""
Checks for a change in intent partition leadership.
Takes the output of leaders -c in json string format before and after
a potential change as input
Returns main.TRUE if no mismatches are detected
Returns main.FALSE if there is a mismatch or on error loading the input
"""
try:
leaders1 = json.loads( leaders1 )
leaders2 = json.loads( leaders2 )
except ( AttributeError, TypeError ):
main.log.exception( self.name + ": Object not as expected" )
return main.FALSE
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
main.log.info( "Checking Intent Paritions for Change in Leadership" )
mismatch = False
for dict1 in leaders1:
if "intent" in dict1.get( "topic", [] ):
for dict2 in leaders2:
if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
mismatch = True
main.log.error( "{0} changed leader from {1} to {2}".
format( dict1.get( "topic", "no-topic" ),
dict1.get( "leader", "no-leader" ),
dict2.get( "leader", "no-leader" ) ) )
if mismatch:
return main.FALSE
else:
return main.TRUE
def report( main ):
"""
Report errors/warnings/exceptions
"""
main.ONOSbench.logReport( main.Cluster.active( 0 ).ipAddress,
[ "INFO",
"FOLLOWER",
"WARN",
"flow",
"ERROR",
"Except" ],
"s" )
main.log.info( "ERROR report: \n" )
for ctrl in main.Cluster.active():
main.ONOSbench.logReport( ctrl.ipAddress,
[ "ERROR" ],
"d" )
main.log.info( "EXCEPTIONS report: \n" )
for ctrl in main.Cluster.active():
main.ONOSbench.logReport( ctrl.ipAddress,
[ "Except" ],
"d" )
main.log.info( "WARNING report: \n" )
for ctrl in main.Cluster.active():
main.ONOSbench.logReport( ctrl.ipAddress,
[ "WARN" ],
"d" )
def flowDuration( main ):
"""
Check age of flows to see if flows are being overwritten
"""
import time
main.log.info( "Getting current flow durations" )
flowsJson1 = main.Cluster.active( 0 ).REST.flows()
try:
flowsJson1 = json.loads( flowsJson1 )
except ValueError:
main.log.error( "Unable to read flows" )
return main.FALSE
flowLife = []
waitFlowLife = []
for flow in flowsJson1:
if flow[ 'appId' ] == "org.onosproject.net.intent":
flowLife.append( flow[ 'life' ] )
main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
time.sleep( main.flowDurationSleep )
main.log.info( "Getting new flow durations" )
flowsJson2 = main.Cluster.active( 0 ).REST.flows()
try:
flowsJson2 = json.loads( flowsJson2 )
except ValueError:
main.log.error( "Unable to read flows" )
return main.FALSE
for flow in flowsJson2:
if flow[ 'appId' ] == "org.onosproject.net.intent":
waitFlowLife.append( flow[ 'life' ] )
main.log.info( "Determining whether flows where overwritten" )
if len( flowLife ) == len( waitFlowLife ):
for i in range( len( flowLife ) ):
if waitFlowLife[ i ] - flowLife[ i ] < main.flowDurationSleep:
return main.FALSE
else:
return main.FALSE
return main.TRUE
def ProtectedIntentCheck( main ):
intent = main.Cluster.active( 0 ).REST.intents()
main.log.debug( intent )
main.stop()
if "Protection" in intent:
return main.TRUE
return main.FALSE