[Kimchi-devel] [PATCH V3] Add OVS bridges recognition support

Lucio Correia luciojhc at linux.vnet.ibm.com
Wed Nov 25 11:16:38 UTC 2015


Allow bridged networks to be created from OVS bridges, and
adapt VM XML to work with OVS networks.

In some distributions, i.e. Fedora, the directories "bridge"
and "brif" are not created for OVS bridges, and they are the
method Kimchi uses to detect bridges. This patch also fixes
that by recognizing OVS bridges through OVS commands,
allowing networks to be created using OVS bridges in those
distributions.

Signed-off-by: Lucio Correia <luciojhc at linux.vnet.ibm.com>

This patch depends on [PATCH V4] Support Linux Bridge creation.

Changes in V3:
- Added error KCHNET0026E


---
 src/wok/plugins/kimchi/i18n.py             |  1 +
 src/wok/plugins/kimchi/model/networks.py   |  8 +++++
 src/wok/plugins/kimchi/netinfo.py          | 53 ++++++++++++++++++++++++++++--
 src/wok/plugins/kimchi/xmlutils/network.py |  5 +++
 4 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/src/wok/plugins/kimchi/i18n.py b/src/wok/plugins/kimchi/i18n.py
index a72f1ee..de7962a 100644
--- a/src/wok/plugins/kimchi/i18n.py
+++ b/src/wok/plugins/kimchi/i18n.py
@@ -270,6 +270,7 @@ messages = {
     "KCHNET0023E": _("Unable to get XML definition for interface %(name)s. Details: %(err)s"),
     "KCHNET0024E": _("Unable to redefine interface %(name)s. Details: %(err)s"),
     "KCHNET0025E": _("Unable to create bridge %(name)s. Details: %(err)s"),
+    "KCHNET0026E": _("Open VSwitch bridges can only host bridged networks."),
 
     "KCHSR0001E": _("Storage server %(server)s was not used by Kimchi"),
 
diff --git a/src/wok/plugins/kimchi/model/networks.py b/src/wok/plugins/kimchi/model/networks.py
index 89c8c3a..3e75d7f 100644
--- a/src/wok/plugins/kimchi/model/networks.py
+++ b/src/wok/plugins/kimchi/model/networks.py
@@ -178,9 +178,17 @@ class NetworksModel(object):
 
         # User specified bridge interface, simply use it
         self._ensure_iface_up(iface)
+        params['ovs'] = False
         if netinfo.is_bridge(iface):
             params['bridge'] = iface
 
+            if netinfo.is_ovs_bridge(iface):
+                params['ovs'] = True
+
+                # OVS bridges don't work with macvtap
+                if params['connection'] != "bridge":
+                    raise InvalidParameter('KCHNET0026E')
+
         # User wants Linux bridge network, but didn't specify bridge interface
         elif params['connection'] == "bridge":
             # create Linux bridge interface first and use it as actual iface
diff --git a/src/wok/plugins/kimchi/netinfo.py b/src/wok/plugins/kimchi/netinfo.py
index c5746d7..ff91489 100644
--- a/src/wok/plugins/kimchi/netinfo.py
+++ b/src/wok/plugins/kimchi/netinfo.py
@@ -21,6 +21,9 @@ import ethtool
 import glob
 import os
 
+from distutils.spawn import find_executable
+from wok.utils import run_command
+from wok.utils import wok_log
 
 NET_PATH = '/sys/class/net'
 NIC_PATH = '/sys/class/net/*/device'
@@ -73,13 +76,51 @@ def is_vlan(iface):
 
 
 def bridges():
-    return [b.split('/')[-2] for b in glob.glob(BRIDGE_PATH)]
+    return list(set([b.split('/')[-2] for b in glob.glob(BRIDGE_PATH)] +
+                    ovs_bridges()))
 
 
 def is_bridge(iface):
     return iface in bridges()
 
 
+# In some distributions, like Fedora, the files bridge and brif are not created
+# under /sys/class/net/<ovsbridge> for OVS bridges. These specific functions
+# allows one to differentiate OVS bridges from other types of bridges.
+def ovs_bridges():
+    ovs_cmd = find_executable("ovs-vsctl")
+
+    # openvswitch not installed: there is no OVS bridge configured
+    if ovs_cmd is None:
+        return []
+
+    out, error, rc = run_command([ovs_cmd, '--oneline', 'list-br'])
+    if rc != 0:
+        wok_log.info("Error listing OVS bridges")
+        return []
+
+    return list(set(out.split('\n')) - set(['']))
+
+
+def is_ovs_bridge(iface):
+    return iface in ovs_bridges()
+
+
+def ovs_bridge_ports(ovsbr):
+    ovs_cmd = find_executable("ovs-vsctl")
+
+    # openvswitch not installed: there is no OVS bridge configured
+    if ovs_cmd is None:
+        return []
+
+    out, error, rc = run_command([ovs_cmd, '--oneline', 'list-ports', ovsbr])
+    if rc != 0:
+        wok_log.info("Error listing OVS bridge ports for %s" % str(ovsbr))
+        return []
+
+    return list(set(out.split('\n')) - set(['']))
+
+
 def all_interfaces():
     return [d.rsplit("/", 1)[-1] for d in glob.glob(NET_PATH + '/*')]
 
@@ -91,11 +132,19 @@ def slaves(bonding):
 
 
 def ports(bridge):
+    if bridge in ovs_bridges():
+        return ovs_bridge_ports(bridge)
+
     return os.listdir(BRIDGE_PORTS % bridge)
 
 
 def is_brport(nic):
-    return os.path.exists(NET_BRPORT % nic)
+    ovs_brports = []
+
+    for ovsbr in ovs_bridges():
+        ovs_brports += ovs_bridge_ports(ovsbr)
+
+    return os.path.exists(NET_BRPORT % nic) or nic in ovs_brports
 
 
 def is_bondlave(nic):
diff --git a/src/wok/plugins/kimchi/xmlutils/network.py b/src/wok/plugins/kimchi/xmlutils/network.py
index 14c7e13..f9594e6 100644
--- a/src/wok/plugins/kimchi/xmlutils/network.py
+++ b/src/wok/plugins/kimchi/xmlutils/network.py
@@ -95,6 +95,11 @@ def to_network_xml(**kwargs):
     if bridge:
         network.append(E.bridge(name=bridge))
 
+        # Add virtualport element for openvswitch bridges
+        ovs = kwargs.get('ovs')
+        if ovs:
+            network.append(E.virtualport(type='openvswitch'))
+
     # None means is Isolated network, {} means default mode nat
     params = kwargs.get('forward', {"mode": None})
     forward = _get_forward_elem(**params)
-- 
1.9.1




More information about the Kimchi-devel mailing list