SDN in Action: Build a VXLAN tunnel by making Python-based API Calls on OpenDaylight and Provide the DCI service

 

薛国锋                                      xueguofeng2011@gmail.com

 

 

今天做了个小实验,通过Python程序调用OpenDaylight的北向API,在两个DC之间建立VXLAN隧道,实现DCIDC内部采用Mininet c0控制器和OpenFlow协议,跨DC采用OpenDaylightOVSDB协议实现DC互联。通过本次实验深刻领悟到,SDN控制器实际上就是一个API Gateway ,提供北向RESTful API以及南向控制协议(OpenFlowOVSDBNetConfBGP-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: 

      

wKiom1nQTlqiBfOeAACc9OwZo7E686.png


wKiom1nQTqLiHSKoAADgM6WoTrw071.png


1 Run OpenDaylight and install the necessary features


wKiom1nQTv2BawoXAAE8w8PvbQA100.png


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:

wKioL1nQT1yj9NeLAAE2p-cDfDs143.png


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

wKiom1nQUK-zZXfsAAIAg_OQE0U017.png

wKioL1nQUJbT23b9AAF2gUQYQR4489.png

Check DC2

mininet>sh netstat –an | grep 6640

mininet>sh ovs-vsctl show

wKiom1nQUjSicUmTAAIVQLh2RTc450.png

wKiom1nQUlzjatKXAAF4jMDULlI671.png


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'])


wKiom1nQUpPAbmG9AAFPB34a--w120.png

Make the API calls by Yangman:

wKioL1nQUtSi88BmAADX7g-vj4A526.png