SDN in Action: Build a VXLAN tunnel by making Python-based API Calls on OpenDaylight and Provide the DCI service
今天做了个小实验,通过Python程序调用OpenDaylight的北向API,在两个DC之间建立VXLAN隧道,实现DCI;DC内部采用Mininet c0控制器和OpenFlow协议,跨DC采用OpenDaylight及OVSDB协议实现DC互联。通过本次实验深刻领悟到,SDN控制器实际上就是一个API Gateway ,提供北向RESTful API以及南向控制协议(OpenFlow、OVSDB、NetConf、BGP-LS等)之间的转换,实现网络动态可编程和业务自动化部署J
Today we will play with Python, making Python-based API calls on OpenDaylight and building a VXLAN tunnel between two DCs. Inside each DC, the Mininet C0 controller and OpenFlow are deployed; and with OVSDB, OpenDaylight manages both DCs and provides the interconnect between them. After this test, we would be deeply impressed that the SDN controller is a natural API gateway providing the conversion between NB RESTful API and SB control protocols, such as OpenFlow, OVSDB, NetConf and BGP-LS, etc; and to provide the programmability for network automation and service agility. Below is the physical and logicaldesign and topology:
1 Run OpenDaylight and install the necessary features
opendaylight-user@root>feature:installodl-aaa-authn
opendaylight-user@root>feature:installodl-restconf-all
opendaylight-user@root>feature:installodl-dlux-core
opendaylight-user@root>feature:installodl-dluxapps-yangman
opendaylight-user@root>feature:installodl-dluxapps-topology
opendaylight-user@root>feature:installodl-l2switch-all
opendaylight-user@root>feature:installwebconsole
opendaylight-user@root>feature:installodl-mdsal-apidocs
opendaylight-user@root>feature:installodl-ovsdb-southbound-api
Please check the below web link for OVSDB user guide:
http://docs.opendaylight.org/en/stable-carbon/user-guide/ovsdb-user-guide.html
2 Set up DC1 – Mininet
Create the custom topology file – “dc1.py”:
from mininet.topo import Topo
class MyTopo( Topo ):
def__init__( self ):
#initilaize topology
Topo.__init__( self )
# addhosts and switches
h11 =self.addHost( 'h11',ip= '10.0.0.1')
h12 =self.addHost( 'h12',ip= '10.0.0.2')
s11 =self.addSwitch( 's11' )
s12 =self.addSwitch( 's12' )
s10 =self.addSwitch( 's10' )
# addlinks
self.addLink(h11,s11)
self.addLink(h12,s12)
self.addLink(s12,s10)
self.addLink(s10,s11)
topos = { 'mytopo': ( lambda: MyTopo() ) }
Create the virtual DC1 with “dc1.py”::
gset@ubuntu:~$sudo mn --custom dc1.py --topo mytopo
Configure OVS to listen for the connection initiated by the OVSDB Southbound Plugin of OpenDaylight:
mininet>sh ovs-vsctl set-manager ptcp:6640
3 Set up DC2 – Mininet
Create the custom topology file – “dc2.py”:
from mininet.topo import Topo
class MyTopo( Topo ):
def__init__( self ):
#initilaize topology
Topo.__init__( self )
# addhosts and switches
h21 =self.addHost( 'h21',ip= '10.0.0.3')
h22 =self.addHost( 'h22',ip= '10.0.0.4')
s21 =self.addSwitch( 's21' )
s22 =self.addSwitch( 's22' )
s20 =self.addSwitch( 's20' )
# addlinks
self.addLink(h21,s21)
self.addLink(h22,s22)
self.addLink(s22,s20)
self.addLink(s20,s21)
topos = { 'mytopo': ( lambda: MyTopo() ) }
Create the virtual DC2 with “dc2.py”:
gset@ubuntu:~$sudo mn --custom dc2.py --topo mytopo
Configure OVS to listen for the connection initiated by the OVSDB Southbound Plugin of OpenDaylight:
mininet>sh ovs-vsctlset-manager ptcp:6640
4 Python Programming to MakeAPI Calls
Install Geany IDE and the Requests Library in Python:
gset@ubuntu:~$sudo apt-getinstall geany
gset@ubuntu:~$geany
gset@ubuntu:~ $pip installrequests
Set Build Commands of Geany IDE:
Configure the OVSDB Southbound Plugin in OpenDaylight toactively connect to DC1 and DC2:
import requests
import json
header = {'content-type': 'application/json'}
commamd10 = {"network-topology:node": [{
"node-id":"ovsdb://DC1",
"connection-info":
{
"ovsdb:remote-port":"6640", "ovsdb:remote-ip": "192.168.100.144" }}]}
commamd20 = {"network-topology:node": [{
"node-id":"ovsdb://DC2",
"connection-info":
{
"ovsdb:remote-port":"6640", "ovsdb:remote-ip": "192.168.100.145" }}]}
# Making the API Call on OpenDaylight toconnect to DC1
r1 = requests.put(url='http://192.168.100.129:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:%2F%2FDC1',
data=json.dumps(commamd10),
headers=header,
auth=('admin','admin')
)
# Making the API Call on OpenDaylight to connect to DC2
r2 = requests.put(url='http://192.168.100.129:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:%2F%2FDC2',
data=json.dumps(commamd20),
headers=header,
auth=('admin','admin')
)
Configure and manage the vxlan ports of DC1 and DC2:
import requests
import json
header = {'content-type': 'application/json'}
commamd11 = { "termination-point":
[{
"tp-id":"vxlanport",
"ovsdb:name":"vxlanport",
"ovsdb:interface-type":"ovsdb:interface-type-vxlan",
"ovsdb:options":
[{
"option":"remote_ip", "value": "192.168.100.145"
}]}]}
commamd21 = { "termination-point":
[{
"tp-id":"vxlanport",
"ovsdb:name":"vxlanport",
"ovsdb:interface-type":"ovsdb:interface-type-vxlan",
"ovsdb:options":
[{
"option":"remote_ip", "value": "192.168.100.144"
}]}]}
# Making the API Call on OpenDaylight to create the vxlan port on s10 of DC1
r1 = requests.put(url='http://192.168.100.129:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:%2F%2FDC1%2Fbridge%2Fs10/termination-point/vxlanport',
data=json.dumps(commamd11),
headers=header,
auth=('admin','admin')
)
# Making the API Call on OpenDaylight to create the vxlan port on s20 of DC2
r2 = requests.put(url='http://192.168.100.129:8181/restconf/config/network-topology:network-topology/topology/ovsdb:1/node/ovsdb:%2F%2FDC1%2Fbridge%2Fs20/termination-point/vxlanport',
data=json.dumps(commamd21),
headers=header,
auth=('admin','admin')
)
5 Check the Network
Check DC1:
mininet>sh netstat –an | grep 6640
mininet>sh ovs-vsctl show
Check DC2:
mininet>sh netstat –an | grep 6640
mininet>sh ovs-vsctl show
Read the network topology from OpenDaylight by Python making API calls:
import requests
import json
header = {'content-type': 'application/json'}
r = requests.get( url='http://192.168.100.129:8181/restconf/operational/network-topology:network-topology',
headers=header,
auth=('admin','admin')
)
print(r.status_code)
print(r.headers['content-type'])
print(r.url)
rj = r.json()
print('\n'+rj['network-topology']['topology'][0]['topology-id'])
print('\n'+rj['network-topology']['topology'][1]['topology-id'])
for node inrj['network-topology']['topology'][0]['node']:
print('\n'+node['node-id'])
if'termination-point' in node:
forport in node['termination-point']:
print('----'+ port['tp-id'])
Make the API calls by Yangman: