Merge "Add flow rest api driver"
diff --git a/TestON/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index d7e0572..42b7680 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -419,8 +419,6 @@
def addPointIntent( self,
ingressDevice,
egressDevice,
- ip="DEFAULT",
- port="DEFAULT",
appId='org.onosproject.cli',
ingressPort="",
egressPort="",
@@ -433,7 +431,9 @@
ipSrc="",
ipDst="",
tcpSrc="",
- tcpDst="" ):
+ tcpDst="",
+ ip="DEFAULT",
+ port="DEFAULT" ):
"""
Description:
Adds a point-to-point intent ( uni-directional ) by
@@ -498,6 +498,11 @@
intentJson[ 'selector' ][ 'criteria' ].append( {
"type":"ETH_TYPE",
"ethType":2048 } )
+ elif ethType:
+ intentJson[ 'selector' ][ 'criteria' ].append( {
+ "type":"ETH_TYPE",
+ "ethType":ethType } )
+
if ethSrc:
intentJson[ 'selector' ][ 'criteria' ].append(
{ "type":"ETH_SRC",
@@ -916,6 +921,213 @@
main.log.exception( e )
return None
+ def getFlows( self, device, flowId=0, ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Gets all the flows of the device or get a specific flow in the
+ device by giving its flow ID
+ Required:
+ str device - device/switch Id
+ Optional:
+ int/hex flowId - ID of the flow
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port \
+ from topo file" )
+ port = self.port
+ url = "/flows/" + device
+ if flowId:
+ url += "/" + str( int( flowId ) )
+ print url
+ response = self.send( ip, port, url=url )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ output = response[ 1 ]
+ a = json.loads( output ).get( 'flows' )
+ b = json.dumps( a )
+ return b
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+
+ def addFlow( self,
+ deviceId,
+ appId=0,
+ ingressPort="",
+ egressPort="",
+ ethType="",
+ ethSrc="",
+ ethDst="",
+ bandwidth="",
+ lambdaAlloc=False,
+ ipProto="",
+ ipSrc="",
+ ipDst="",
+ tcpSrc="",
+ tcpDst="",
+ ip="DEFAULT",
+ port="DEFAULT" ):
+ """
+ Description:
+ Creates a single flow in the specified device
+ Required:
+ * deviceId: id of the device
+ Optional:
+ * ingressPort: port ingress device
+ * egressPort: port of egress device
+ * ethType: specify ethType
+ * ethSrc: specify ethSrc ( i.e. src mac addr )
+ * ethDst: specify ethDst ( i.e. dst mac addr )
+ * ipProto: specify ip protocol
+ * ipSrc: specify ip source address with mask eg. ip#/24
+ * ipDst: specify ip destination address eg. ip#/24
+ * tcpSrc: specify tcp source port
+ * tcpDst: specify tcp destination port
+ Returns:
+ Returns main.TRUE for successful requests; Returns main.FALSE
+ if error on requests;
+ Returns None for exceptions
+ NOTE:
+ The ip and port option are for the requests input's ip and port
+ of the ONOS node
+ """
+ try:
+
+ flowJson = { "priority":100,
+ "isPermanent":"true",
+ "timeout":0,
+ "deviceId":deviceId,
+ "treatment":{"instructions":[]},
+ "selector": {"criteria":[]}}
+
+ if appId:
+ flowJson[ "appId" ] = appId
+
+ if egressPort:
+ flowJson[ 'treatment' ][ 'instructions' ].append(
+ { "type":"OUTPUT",
+ "port":egressPort } )
+ if ingressPort:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IN_PORT",
+ "port":ingressPort } )
+ if ethType == "IPV4":
+ flowJson[ 'selector' ][ 'criteria' ].append( {
+ "type":"ETH_TYPE",
+ "ethType":2048 } )
+ elif ethType:
+ flowJson[ 'selector' ][ 'criteria' ].append( {
+ "type":"ETH_TYPE",
+ "ethType":ethType } )
+ if ethSrc:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"ETH_SRC",
+ "mac":ethSrc } )
+ if ethDst:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"ETH_DST",
+ "mac":ethDst } )
+ if ipSrc:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IPV4_SRC",
+ "ip":ipSrc } )
+ if ipDst:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IPV4_DST",
+ "ip":ipDst } )
+ if tcpSrc:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"TCP_SRC",
+ "tcpPort": tcpSrc } )
+ if tcpDst:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"TCP_DST",
+ "tcpPort": tcpDst } )
+ if ipProto:
+ flowJson[ 'selector' ][ 'criteria' ].append(
+ { "type":"IP_PROTO",
+ "protocol": ipProto } )
+
+ # TODO: Bandwidth and Lambda will be implemented if needed
+
+ main.log.debug( flowJson )
+
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
+ port = self.port
+ url = "/flows/" + deviceId
+ response = self.send( ip,
+ port,
+ method="POST",
+ url=url,
+ data=json.dumps( flowJson ) )
+ if response:
+ if 201:
+ main.log.info( self.name + ": Successfully POST flow" +
+ "in device: " + str( deviceId ) )
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
+ def removeFlow( self, deviceId, flowId,
+ ip="DEFAULT", port="DEFAULT" ):
+ """
+ Description:
+ Remove specific device flow
+ Required:
+ str deviceId - id of the device
+ str flowId - id of the flow
+ Return:
+ Returns main.TRUE if successfully deletes flows, otherwise
+ Returns main.FALSE, Returns None on error
+ """
+ try:
+ output = None
+ if ip == "DEFAULT":
+ main.log.warn( "No ip given, reverting to ip from topo file" )
+ ip = self.ip_address
+ if port == "DEFAULT":
+ main.log.warn( "No port given, reverting to port " +
+ "from topo file" )
+ port = self.port
+ # NOTE: REST url requires the intent id to be in decimal form
+ query = "/" + str( deviceId ) + "/" + str( int( flowId ) )
+ response = self.send( ip,
+ port,
+ method="DELETE",
+ url="/flows" + query )
+ if response:
+ if 200 <= response[ 0 ] <= 299:
+ return main.TRUE
+ else:
+ main.log.error( "Error with REST request, response was: " +
+ str( response ) )
+ return main.FALSE
+ except Exception as e:
+ main.log.exception( e )
+ return None
+
def checkFlowsState( self , ip="DEFAULT", port="DEFAULT" ):
"""
Description:
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index b321492..1d5322d 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -445,7 +445,7 @@
main.cleanup()
main.exit()
- def pingIpv6Hosts(self, hostList, prefix='1000::')
+ def pingIpv6Hosts(self, hostList, prefix='1000::'):
"""
IPv6 ping all hosts in hostList. If no prefix passed this will use
default prefix of 1000::