summaryrefslogtreecommitdiffstats
path: root/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py
diff options
context:
space:
mode:
Diffstat (limited to 'vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py')
-rwxr-xr-xvstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py183
1 files changed, 183 insertions, 0 deletions
diff --git a/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py b/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py
new file mode 100755
index 00000000..46045950
--- /dev/null
+++ b/vstf/vstf/agent/env/vswitch_plugins/ovs_plugin.py
@@ -0,0 +1,183 @@
+"""
+Created on 2015-10-10
+
+@author: y00228926
+"""
+import os
+import shutil
+import logging
+import time
+import re
+
+from vstf.agent.env.vswitch_plugins import model
+from vstf.common.utils import check_and_kill, check_and_rmmod, check_call, check_output, \
+ get_eth_by_bdf, my_mkdir, call
+
+LOG = logging.getLogger(__name__)
+
+
+class OvsPlugin(model.VswitchPlugin):
+
+ def __init__(self):
+ self.daemons = ['ovs-vswitchd', 'ovsdb-server']
+ self.mods = ['openvswitch']
+ self.dirs = {'db': "/usr/local/etc/openvswitch"}
+ self.cmds = []
+ self.cmds.append("mkdir -p /usr/local/etc/openvswitch")
+ self.cmds.append("ovsdb-tool create /usr/local/etc/openvswitch/conf.db")
+ self.cmds.append("ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
+ --remote=db:Open_vSwitch,Open_vSwitch,manager_options \
+ --private-key=db:Open_vSwitch,SSL,private_key \
+ --certificate=db:Open_vSwitch,SSL,certificate \
+ --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
+ --pidfile --detach")
+ self.cmds.append("ovs-vsctl --no-wait init")
+ self.cmds.append("ovs-vswitchd --pidfile --detach")
+ self.initialized = False
+
+ def init(self):
+ if not self.initialized:
+ self._start_servers()
+ self.initialized = True
+
+ def clean(self):
+ """clean for ovs. Rmmod openvswitch.ko, kill openvswitch daemon process.
+
+ """
+ for process in self.daemons:
+ check_and_kill(process)
+ for mod in self.mods:
+ check_and_rmmod(mod)
+ for _, directory in self.dirs.items():
+ if os.path.isdir(directory):
+ LOG.info('rm -rf %s', directory)
+ shutil.rmtree(directory, ignore_errors=True)
+ self.initialized = False
+ return True
+
+ def create_br(self, br_cfg):
+ """Create a bridge(virtual switch). Return True for success, return False for failure.
+
+ :param dict br_cfg: configuration for bridge creation like
+ {
+ "type": "ovs",
+ "name": "ovs1",
+ "uplinks": [
+ {
+ "bdf": "04:00.0",
+ "vlan_mode": "access",
+ "vlan_id": "1"
+ }
+ ],
+ "vtep": {},
+ }
+
+ """
+ self.init()
+ name, uplinks = br_cfg['name'], br_cfg['uplinks']
+
+ check_call("ovs-vsctl add-br %s" % (name), shell=True)
+ if br_cfg['vtep']: # vxlan supports
+ local_ip, remote_ip = br_cfg['vtep']['local_ip'], br_cfg['vtep']['remote_ip']
+ assert len(uplinks) == 1
+ uplink = uplinks[0]
+ device = get_eth_by_bdf(uplink['bdf'])
+ time.sleep(0.5)
+ vtep = 'vx1'
+ check_call("ifconfig %s %s up" % (device, local_ip), shell=True)
+ check_call("ovs-vsctl add-port %s %s" % (name, vtep), shell=True)
+ check_call("ovs-vsctl set interface %s type=vxlan options:remote_ip=%s" % (vtep, remote_ip), shell=True)
+ for uplink in uplinks:
+ device = get_eth_by_bdf(uplink['bdf'])
+ vlan_mode = uplink['vlan_mode']
+ vlan_id = uplink['vlan_id']
+ check_call("ip link set dev %s up" % device, shell=True)
+ call("ethtool -A %s rx off tx off " % device, shell=True)
+ check_call("ovs-vsctl add-port %s %s" % (name, device), shell=True)
+ if vlan_mode == 'trunk':
+ check_call("ovs-vsctl set port %s trunks=%s" % (device, vlan_id), shell=True)
+ elif vlan_mode == 'access':
+ check_call("ovs-vsctl set port %s tag=%s" % (device, vlan_id), shell=True)
+ else:
+ raise Exception("unreconized vlan_mode:%s" % vlan_mode)
+ return True
+
+ def set_tap_vid(self, tap_cfg):
+ """set vlan id or vxlan id for tap device(virtual nic for vm).
+ return True for success, return False for failure.
+
+ :param dict tap_cfg: dictionary config for tap device like
+ {
+ "tap_name": "tap_in",
+ "vlan_mode": "access",
+ "vlan_id": "1"
+ }
+
+ """
+ port, vlan_mode, vlan = tap_cfg['tap_name'], tap_cfg['vlan_mode'], tap_cfg['vlan_id']
+ assert vlan_mode in ('access', 'vxlan')
+ if int(vlan) > '4095':
+ # vxlan setting
+ self.__set_tap_vid(port, "vxlan", vlan)
+ else:
+ # vlan setting
+ self.__set_tap_vid(port, vlan_mode, vlan)
+ return True
+
+ def set_fastlink(self, br_cfg):
+ """connect two ports directly, so that packets comes from any one port be forwarded to the other.
+ return True for success, return False for failure.
+
+ :param dict br_cfg: dictionary configuration for linking ports.
+ {
+ "name": "ovs1",
+ "fastlink": [
+ {
+ "inport": "04:00.0",
+ "outport": "tap_in"
+ }
+ ]
+ }
+ """
+ br_name = br_cfg['name']
+ for fast_cfg in br_cfg['fastlink']:
+ p1, p2 = fast_cfg['inport'], fast_cfg['outport']
+ self.__fastlink(br_name, p1, p2)
+ return True
+
+ def _start_servers(self):
+ for _, directory in self.dirs.items():
+ my_mkdir(directory)
+ for mod in self.mods:
+ check_call("modprobe %s" % mod, shell=True)
+ for cmd in self.cmds:
+ check_call(cmd, shell=True)
+ return True
+
+ def __set_tap_vid(self, port, vlan_mode, vlan_id):
+ if vlan_mode == 'vxlan':
+ raise Exception("don't support vxlan setting right now.")
+ elif vlan_mode == 'trunk':
+ check_call("ovs-vsctl set port %s trunks=%s" % (port, vlan_id), shell=True)
+ else:
+ check_call("ovs-vsctl set port %s tag=%s" % (port, vlan_id), shell=True)
+
+ def __fastlink(self, br, p1, p2):
+ LOG.info("_fastlink(%s,%s,%s)", br, p1, p2)
+ p1 = p1.replace(' ', '')
+ p2 = p2.replace(' ', '')
+ bdfs = check_output("lspci |grep Eth | awk '{print $1}'", shell=True).splitlines()
+ if p1 in bdfs:
+ p1 = get_eth_by_bdf(p1)
+ if p2 in bdfs:
+ p2 = get_eth_by_bdf(p2)
+ ovs_port = {}
+ buf = check_output("ovs-ofctl show %s" % br, shell=True)
+ port_info = re.compile(r"[0-9]+\(.*\)", re.IGNORECASE | re.MULTILINE)
+ for s in port_info.findall(buf):
+ port_num, interface = s.replace('(', ' ').replace(')', ' ').split()
+ ovs_port[interface] = port_num
+ pn1, pn2 = ovs_port[p1], ovs_port[p2]
+ check_call("ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" % (br, pn1, pn2), shell=True)
+ check_call("ovs-ofctl add-flow %s in_port=%s,priority=100,action=output:%s" % (br, pn2, pn1), shell=True)
+ return True