TestON Third party integration - Paxterra/TestON GitHub Wiki
#1.OpenDaylight Controller
Introduction of OpenDaylight Controller:
Software Defined Network (SDN) is a new way of deploying network infrastructure.Central to the SDN effort is the Controller which provides the ability to deploy software to control the network gear and redeploy as needed.The vision is to have a modular Controller with a well published Northbound API for network applications to write towards while utilizing Southbound protocols such as OpenFlow to communicate with supported downstream network nodes. These functionalities can be acheived by OpenDaylight controller. Open Daylight Controller supports not only the OpenFlow protocol but also other open protocols to allow communication with devices which have OpenFlow elements. It also includes a Northbound API to allow a software which will work with the Controller in controlling the network. Architecture of OpenDaylight Controller: The Open Daylight Controller is a pure software and as a JVM it can be run on any OS as long as it supports Java. The following picture shows the structure of the OpenDaylight Controller.
The Controller exposes open Northbound APIs which are used by Applications.We support the OSGi framework and bidirectional REST for the Northbound API. OSGi framework is used for applications that will run in the same address space as the Controller while the REST (web based) API is used for Apps that do not run in the same address space (or even the same metal) as the Controller. The business logic and algorithms reside in the Apps. These Apps use the Controller to gather network intelligence, runs its algorithm to do analytics and then use the Controller to orchestrate the new rules throughout the network.
OSGI Framework:
The OSGi framework allows dynamically linking plugins for the evolving southbound protocols. The SAL(Service Abstraction Layer) provides basic services like Device Discovery which are used by modules like Topology Manager to build the topology and device capabilities. Services are constructed using the features exposed by the plugins (based on the presence of a plugin and capabilities of a network device). Based on the service request the SAL maps to the appropriate plugin and thus uses the most appropriate Southbound protocol to interact with a given network device. Data Packet services in OpenDaylight controller consist of: •Topology Service is a set of services that allow to convey topology information like a new node a new link has been discovered. •Flow Programming service is supposed to provide the necessary logic to program in the different agents a Match/Actions rule. •Statistics service of Data packet in OpenDaylight consist of *Flow *Node Connector. *Queue.
OpenDaylight Controller(GUI):
The GUI is implemented as an APP and uses the NB REST API to interact with the other modules of the controller. This architecture thus ensures that whatever is possible with the GUI is also available via REST API and thus the Controller can be integrated easily into other management or orchestration systems. The OpenFlow enabled Switches connect to two or more instances of the Controller via persistent point-to-point TCP/IP connection. On the northbound side the interaction between the controller and the applications is done via RESTful webservices for all the Request-Response type of interaction, being those based on HTTP and being HTTP based on non-persistent connections between the server and the client, it's possible to leverage all the high-available techniques used to give resilience on the WEB, like: The Open Daylight Controller supports a Cluster based High Availability model. There are several instances of the Open Daylight Controller which logically act as one logical controller. This not only gives a fine grain redundancy but also allows a scale-out model for linear scalability. The OpenFlow enabled Switches connect to two or more instances of the Controller via persistent point-to-point TCP/IP connection. On the northbound side the interaction between the controller and the applications is done via RESTful webservices for all the Request-Response type of interaction, being those based on HTTP and being HTTP based on non-persistent connections between the server and the client, it's possible to leverage all the high-available techniques used to give resilience on the WEB.
Rest API's used in OpenDaylight are: •Topology REST APIs •Host Tracker REST API's •Flow Programmer REST API's •Static Routing REST API's •Statistics REST API's •Subnets REST API's •Switch Manager REST API's •Container Manager REST API's •Connection Manager REST API's All REST API's in OpenDaylight provides HTTP authentication for Local users created on the Controller. The Local user creation can only be done via the web graphical user interface and these users can be given authorization to handle one or more slices. The username/password created for an individual user on the web graphical user interface can be used over the REST API to access relevant resources.
OpenDaylight Controller Set Up From CLI:
OpenDaylight controller can be pulled from CLI by using following commands:
• git clone ssh://@git.opendaylight.org:29418/controller.git
This Command pulls the OpenDaylight respository.
PreRequisites for OpenDaylight setup:
• Maven 3.04 or greater(Check the version of by using command mvn
-v).
• JVM 1.7+(Set environment variables).
Run the command – cd opendaylight/distrubution/opendaylight/
maven install.
Find the controller - ls target/distribution.opendaylight-0.1.0-SNAPSHOT-osgipackage.zip.
Run the controller cd controller/opendaylight/distrubution/opendaylight/target/distrubution.opendaylight-osgipackage/opendaylight/./run.sh
After running this command, web interface of ODL can be visible at 8080 port as:
OpenDaylight Using Python:
OpenDaylight supports Northbound API to write the test case using python.
Combining Rest and mininet API's calls with ODL Rest API's could be a powerful tool for network application
Here is the sample script which talks about how to leverage Mininet and ODL API calls:
• First create a class for to define topology
class SingleSwitchTopo(Topo):
"Single switch connected to n hosts."
def init(self, n=2, **opts):
// Initialize topology and default options
Topo.init(self, **opts)
// mininet/ovswitch does not want ':'s in the dpid
switch_id = SWITCH_1.translate(None, ':')
switch = self.addSwitch('s1', dpid=switch_id)
for h in range(n):
host = self.addHost('h%s' % (h + 1))
self.addLink(host, switch)
• Next set up the Mininet network:
def setup_mininet_simpleTest():
"Create and test a simple network"
topo = SingleSwitchTopo(n=4)
//net = Mininet(topo)
net = Mininet( topo=topo, controller=lambda name: RemoteController(
name, ip=CONTROLLER ) )
net.start()
Finally set up the complete test which uses API's calls of ODL, Mininet. Here
is the sample test script.
class TestSequenceFunctions(unittest.TestCase):
"""Tests for OpenDaylight
At this point, tests for OpenDaylightFlow and OpenDaylightNode
are intermingled. These could be seperated out into seperate
suites.
"""
def setUp(self):
odl = OpenDaylight()
odl.setup['hostname'] = CONTROLLER
odl.setup['username'] = USERNAME
odl.setup['password'] = PASSWORD
self.flow = OpenDaylightFlow(odl)
self.node = OpenDaylightNode(odl)
self.switch_id_1 = SWITCH_1
self.odl_test_flow_1 = {u'actions': u'DROP',
u'etherType': u'0x800',
u'ingressPort': u'1',
u'installInHw': u'true',
u'name': u'odl-test-flow1',
u'node': {u'@id': self.switch_id_1, u'@type': u'OF'},
u'priority': u'500'}
self.odl_test_flow_2 = {u'actions': u'DROP',
u'etherType': u'0x800',
u'ingressPort': u'2',
u'installInHw': u'true',
u'name': u'odl-test-flow2',
u'node': {u'@id': self.switch_id_1, u'@type': u'OF'},
u'priority': u'500'}
def test_01_delete_flows(self):
"""Clean up from any previous test run, just delete these
flows if they exist.
"""
try:
self.flow.delete(self.odl_test_flow_1['node']['@id'],
self.odl_test_flow_1['name'])
except:
pass
try:
self.flow.delete(self.odl_test_flow_2['node']['@id'],
self.odl_test_flow_2['name'])
except:
pass
Using ODL REST API's calls in Python:
To use ODL REST API integration to get the statistics to generate a traffic details, this can be acheived by the statistic Rest API's.
h = httplib2.Http(".cache")
h.add_credentials('admin', 'admin')
resp,
content
=h.request('http://10.55.17.20:8080/controller/nb/v2/statistics/default/flow',"GET")
allFlowStats = json.loads(content)
flowStats = allFlowStats['flowStatistics']
for fs in flowStats:
print "\nSwitch ID : " + fs['node']['@id']
print '{0:8} {1:8} {2:5} {3:15}'.format('Count', 'Action', 'Port', 'DestIP')
for aFlow in fs['flowStat']:
count = aFlow['packetCount']
actions = aFlow['flow']['actions']
actionType = ''
actionPort = ''
//print actions
if(type(actions) == type(list())):
actionType = actions[1]['@type']
actionPort = actions[1]['port']['@id']
else:
actionType = actions['@type']
actionPort = actions['port']['@id']
dst = aFlow['flow']['match']['matchField'][0]['value']
print
actionPort, dst)
'{0:8}
{1:8}
{2:5}
{3:15}'.format(count,
actionType,
OpenDaylight with TestON:
To access the functionality of OpenDaylight controller in TestON, create a python file which will act as library for openDaylight controller and from this library the user interact to the ODL functions and REST API's. Here is the sample script which demonstrate the working of ODL library.
from future import print_function
import json
import requests
from requests.auth import HTTPBasicAuth
class OpenDaylight(object):
"""
An object holding details to talk to the OpenDaylight REST API
"""
def init(self):
"""Set some mostly reasonable defaults.
"""
self.setup = {'hostname':'localhost',
'port':'8080',
'username':'admin',
'password':'admin',
'path':'/controller/nb/v2/',
'container':'default',
'http':'http://'}
self._base_url = None
self.url = None
self.auth = None
The above sample script will connect to the OpenDaylight web Interface.
def prepare_url(self, app, path):
// the base url we will use for the connection
self._base_url = self.setup['http'] + self.setup['hostname'] + ':' +
self.setup['port'] + self.setup['path']
// the specific path we are building
self.url = self._base_url + app + '/' + self.setup['container'] + path
Above function build the URL for this REST connection which is then stored as
OpenDaylight.url
. The argument 'app' is used to connect to the northbound API. 'path'
argument take specific rest query.
OpenDaylight driver in Test contains list of functions used to perform ODL
functions. For example, add flow, delete flow etc.
def deleteflows(self):
self.flow.delete(self.odl_test_flow_1['node']['@id'],
self.odl_test_flow_1['name'])
self.flow.delete(self.odl_test_flow_2['node']['@id'],
self.odl_test_flow_2['name'])
return main.TRUE
def addflows(self):
self.flow.add(self.odl_test_flow_1)
self.flow.add(self.odl_test_flow_2)
return main.TRUE
def getflows(self):
self.flow.get(node_id=self.switch_id_1, flow_name='odl-test-flow1')
return main.TRUE
In OSPK script we need to include the action what we have used in the .py file
CASE 1
NAME "Delete and add flows in Odl controller"
STEP "Delete and add flows in Odl controller using deleteflows and addflows"
STORE ON Odl DO deleteflows IN result
ASSERT result EQUALS main.TRUE ONPASS "Deleted flows successfully" ONFAIL "Unsuccessfull"
STORE ON Odl DO addflows IN result
ASSERT result EQUALS main.TRUE ONPASS "Addflows successfully" ONFAIL "Unsuccessfull"
STORE ON Odl DO getflows IN result
ASSERT result EQUALS main.TRUE ONPASS "getflows successfully" ONFAIL "Unsuccessfull"
#2.Sprient TestCenter
In StcTest the driver will create a handle to stc library and access the StcPython file inside that. By using StcDriver api's will execute the api's inside the STC python file. The drivers written in the TestON are strictly using python script. The Spirent TestCenter Automation API provides a powerful syntax that allows you to combine object and attribute references to create and manipulate your test configuration.The syntax for a call to a Spirent TestCenter Automation function uses one of the following formats: functionName objectReference[–attributeReference[...]] functionName[value[...]] function names: one of the function names defined for API Example: create get config For aceesing spirent STC you need create a handle to StcPython inside the Spirent library. Self.handle = StcPython() The above mentioned function will create the handle to Spirent Stcpython there we can acess the all python libraries To execute the Spirent Test you need to upload Spirent library inside the TestON “lib” folder Object, Attribute, and Relation References :
- Creating Objects : Object Type Names and Paths
- Referencing Objects : Object Handles
- Referencing Objects : Object paths
- Relation References Creating Objects: Object Type Names and Paths When you create Spirent TestCenter objects, you specify the type of object to be created. For example: MyProject = self.handle.create(project) This call to create produces a single object (type Project) and returns a handle to that object You can also create a set of objects in a single call to the create function by specifying anobject type path name. Path names are sequences of object type names, separated by dots.To use a path name with the create function, you must create the new objects under anexisting object. For example: router = stc.create(BgpRouterConfig , under = project) Referencing Objects: Object Handles In many cases, when you call Spirent TestCenter Automation functions, you either provide or obtain an object handle. A handle is a string value that identifies a Spirent TestCenter Automation object. Object handles are the links between your application and the object hierarchy maintained by Spirent TestCenter API. Object handles are valid for the lifetime of the object. In some circumstances, Spirent TestCenter will create objects on your behalf. Each object description in the Spirent TestCenter Automation Object Reference lists the associated automatic objects. Spirent TestCenter Automation creates a handle when you create an object in your configuration. When you call the create function, the object handle is the return value from the function: Project_handle = stc.create(project,name = 'BgpTest') When the create function returns, the variable project_handle is set to the value of the object handle for the newly created Project object. Your application can then use the object handle to refer to the newly created object in other calls to Spirent TestCenter Automation functions. Note : when you create an object, you must always specify the parent object handle. Using Object Handles : To identify the parent for a new object. With the exception of the Project object, you must specify a parent when you create an object. For example: port = stc.handle.create (Port,under = project_handle) In this example,the 'under' attribute specifies the Project object handle as the parent for the new Port object. The create function returns the handle for the Port object; you use this object handle as the parent for StreamBlock objects or other objects that are children of a Port object. Referencing Objects: Object Paths You can use path name notation to reference objects and object attributes in your test hierarchy. The path name references shorten the command line and reduce the need to search for handles to access objects. When you use the API, a function call identifies an object, or it identifies an object and one (or more) of its attributes. For example: stc.handle.delete (port) stc.handle.config (port,location= "//10.100.0.1/1/1") CLI level : Currently we can run StcTest in CLI level on TestON FrameWork. In CLI level we can run all api's inside the stc driver on command line prompt. And those functions will execute and call the Stc library inside the TestON “lib” folder. After executing the test, the traffic results will be stored in bin folder inside the TestON. The trffic results will be stored in the .csv formated files as per Stc libraries. In TestON 'stcdriver' we can retrive and assert the each and every result generated by STC Test on STC by using “parseresults” api inside the 'stcdriver' def parseresults(self,Attribute,CsvFile) : try : main.log.info("parsing the CSV file for the traffic results") totalrows = len(open('/home/TestON/bin/Untitled/'+CsvFile).readlines()) fp = open("/home/TestON/bin/Untitled/"+CsvFile,'Ur') data_list = [] attributes=[] attribute_values=[] for line in fp: data_list.append(line.strip().split(',')) attribute_values=data_list[totalrows-1] attributes=data_list[totalrows-3] for index in range (0,100) : if attributes[index]==Attribute: main.log.info("Given Attribute Name is:'"+Attribute+"'") main.log.info("Attribute value is:'"+attribute_values[index]+"'") result = attribute_values[index] if result == '0' : main.log.info("Traffic is not generated on this attribute :"+Attribute) return main.FALSE else : return result main.log.info("parsing the CSV file for the traffic results")