core-extra/daemon/core/services/sdn.py

128 lines
4.3 KiB
Python

"""
sdn.py defines services to start Open vSwitch and the Ryu SDN Controller.
"""
import re
from core.service import CoreService
from core.service import ServiceManager
class SdnService(CoreService):
"""
Parent class for SDN services.
"""
_name = "SdnProcess"
_group = "SDN"
_depends = ()
_dirs = ()
_configs = ()
_startindex = 50
_startup = ()
_shutdown = ()
@classmethod
def generateconfig(cls, node, filename, services):
return ""
class OvsService(SdnService):
_name = "OvsService"
_group = "SDN"
_depends = ()
_dirs = ("/etc/openvswitch", "/var/run/openvswitch", "/var/log/openvswitch")
_configs = ('OvsService.sh',)
_startindex = 50
_startup = ('sh OvsService.sh',)
_shutdown = ('killall ovs-vswitchd', 'killall ovsdb-server')
@classmethod
def generateconfig(cls, node, filename, services):
# Check whether the node is running zebra
has_zebra = 0
for s in services:
if s._name == "zebra":
has_zebra = 1
# Check whether the node is running an SDN controller
has_sdn_ctrlr = 0
for s in services:
if s._name == "ryuService":
has_sdn_ctrlr = 1
cfg = "#!/bin/sh\n"
cfg += "# auto-generated by OvsService (OvsService.py)\n"
cfg += "/etc/init.d/openvswitch-switch start < /dev/null\n"
cfg += "ovs-vsctl add-br ovsbr0\n"
cfg += "ifconfig ovsbr0 up\n"
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True:
continue
ifnumstr = re.findall(r"\d+", ifc.name)
ifnum = ifnumstr[0]
# create virtual interfaces
cfg += "ip link add rtr%s type veth peer name sw%s\n" % (ifnum, ifnum)
cfg += "ifconfig rtr%s up\n" % ifnum
cfg += "ifconfig sw%s up\n" % ifnum
# remove ip address of eths because quagga/zebra will assign same IPs to rtr interfaces
# or assign them manually to rtr interfaces if zebra is not running
for ifcaddr in ifc.addrlist:
if ifcaddr.find(".") >= 0:
cfg += "ip addr del %s dev %s\n" % (ifcaddr, ifc.name)
if has_zebra == 0:
cfg += "ip addr add %s dev rtr%s\n" % (ifcaddr, ifnum)
elif ifcaddr.find(":") >= 0:
cfg += "ip -6 addr del %s dev %s\n" % (ifcaddr, ifc.name)
if has_zebra == 0:
cfg += "ip -6 addr add %s dev rtr%s\n" % (ifcaddr, ifnum)
else:
raise ValueError("invalid address: %s" % ifcaddr)
# add interfaces to bridge
cfg += "ovs-vsctl add-port ovsbr0 eth%s\n" % ifnum
cfg += "ovs-vsctl add-port ovsbr0 sw%s\n" % ifnum
# Add rule for default controller if there is one local (even if the controller is not local, it finds it)
cfg += "ovs-vsctl set-controller ovsbr0 tcp:127.0.0.1:6633\n"
# Setup default flows
portnum = 1
for ifc in node.netifs():
if hasattr(ifc, 'control') and ifc.control is True:
continue
cfg += "ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n" % (portnum, portnum + 1)
cfg += "ovs-ofctl add-flow ovsbr0 priority=1000,in_port=%d,action=output:%d\n" % (portnum + 1, portnum)
portnum += 2
return cfg
class RyuService(SdnService):
_name = "ryuService"
_group = "SDN"
_depends = ()
_dirs = ()
_configs = ('ryuService.sh',)
_startindex = 50
_startup = ('sh ryuService.sh',)
_shutdown = ('killall ryu-manager',)
@classmethod
def generateconfig(cls, node, filename, services):
"""
Return a string that will be written to filename, or sent to the
GUI for user customization.
"""
app_path = "/usr/local/lib/python2.7/dist-packages/ryu/app"
cfg = "#!/bin/sh\n"
cfg += "# auto-generated by ryuService (ryuService.py)\n"
cfg += '/usr/local/bin/ryu-manager --observe-links %s/ofctl_rest.py %s/rest_topology.py' % (app_path, app_path)
return cfg
def load_services():
ServiceManager.add(OvsService)
ServiceManager.add(RyuService)