[PATCH] Support Linux Bridge creation

Create linux-bridge with libvirt API. Kimchi was only creating macvtap devices, with has some limitation. For further information, take a look at Kimchi wiki discuss: https://github.com/kimchi-project/kimchi/wiki/Create-guest-network Signed-off-by: Ramon Medeiros <ramonn@linux.vnet.ibm.com> Testing: In my case, i create a new bridge over the interface enp0s25 with name ramon curl -u root -H "Content-Type: application/json" -H "Accept: application/json" "http://localhost:8010/plugins/kimchi/networks" -X POST -d '{"name": "ramon", "connection":"bridge", "interface":"enp0s25", "mode":"linux-bridge"}' To delete, you can remove by UI or: curl -u root -H "Content-Type: application/json" -H "Accept: application/json" "http://localhost:8010/plugins/kimchi/networks/ramon" -X DELETE -d '' --- src/wok/plugins/kimchi/model/networks.py | 35 +++++++++++++++++++++++++++--- src/wok/plugins/kimchi/network.py | 20 +++++++++++++++++ src/wok/plugins/kimchi/xmlutils/network.py | 12 ++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/wok/plugins/kimchi/model/networks.py b/src/wok/plugins/kimchi/model/networks.py index 71ea595..dc34f3f 100644 --- a/src/wok/plugins/kimchi/model/networks.py +++ b/src/wok/plugins/kimchi/model/networks.py @@ -35,10 +35,10 @@ from wok.plugins.kimchi import network as knetwork from wok.plugins.kimchi.osinfo import defaults as tmpl_defaults from wok.plugins.kimchi.xmlutils.network import create_vlan_tagged_bridge_xml from wok.plugins.kimchi.xmlutils.network import to_network_xml - +from wok.plugins.kimchi.xmlutils.network import create_linux_bridge KIMCHI_BRIDGE_PREFIX = 'kb' - +IFCFG = "/etc/sysconfig/network-scripts/ifcfg-" class NetworksModel(object): def __init__(self, **kargs): @@ -160,7 +160,10 @@ class NetworksModel(object): def _set_network_bridge(self, params): try: iface = params['interface'] - if iface in self.get_all_networks_interfaces(): + + if params["mode"] == "linux-bridge": + iface = self._create_linux_bridge(iface) + elif iface in self.get_all_networks_interfaces(): msg_args = {'iface': iface, 'network': params['name']} raise InvalidParameter("KCHNET0006E", msg_args) except KeyError: @@ -172,6 +175,7 @@ class NetworksModel(object): raise InvalidParameter('KCHNET0019E', {'name': iface}) params['bridge'] = iface elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface): + if params.get('vlan_id') is None: params['forward']['dev'] = iface else: @@ -196,6 +200,31 @@ class NetworksModel(object): net_dict['bridge'] and interfaces.append(net_dict['bridge']) return interfaces + def _create_linux_bridge(self, interface): + newBridge = KIMCHI_BRIDGE_PREFIX + interface[-8:] + bridges_list = knetwork.list_bridges() + + bridges = [] + for bridge in bridges_list: + bridges.append(bridge["bridge"]) + + # bridge already exists: create new name + if newBridge in bridges: + for i in range(0,10): + newBridge = KIMCHI_BRIDGE_PREFIX + interface[-7:] + str(i) + if newBridge not in bridges: + break + + # create linux bridge by libvirt + try: + conn = self.conn.get() + iface = conn.interfaceDefineXML(create_linux_bridge(newBridge, interface)) + iface.create() + except libvirt.libvirtError as e: + raise OperationFailed("KCHNET0008E", + {'name': newBridge, 'err': e.get_error_message()}) + return newBridge + def _create_vlan_tagged_bridge(self, interface, vlan_id): # Truncate the interface name if it exceeds 8 characters to make sure # the length of bridge name is less than 15 (its maximum value). diff --git a/src/wok/plugins/kimchi/network.py b/src/wok/plugins/kimchi/network.py index 1433b8a..4612599 100644 --- a/src/wok/plugins/kimchi/network.py +++ b/src/wok/plugins/kimchi/network.py @@ -20,7 +20,9 @@ import ethtool import ipaddr +import os +from wok.utils import run_command APrivateNets = ipaddr.IPNetwork("10.0.0.0/8") BPrivateNets = ipaddr.IPNetwork("172.16.0.0/12") @@ -60,3 +62,21 @@ def get_one_free_network(used_nets, nets_pool=PrivateNets): if net: return net return None + +def list_bridges(): + # get all bridges + _, err, rc = run_command(['brctl', 'show']) + output = _.splitlines() + + # iterate over output + i = 1 + bridges = [] + while (i < len(output)): + + # get bridge name + bridges.append({"bridge": output[i].split('\t')[0], + "interface": output[i].split('\t')[5]}) + i += 1 + + return bridges + diff --git a/src/wok/plugins/kimchi/xmlutils/network.py b/src/wok/plugins/kimchi/xmlutils/network.py index c73aad9..2fdf8d4 100644 --- a/src/wok/plugins/kimchi/xmlutils/network.py +++ b/src/wok/plugins/kimchi/xmlutils/network.py @@ -120,3 +120,15 @@ def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id): type='bridge', name=bridge) return ET.tostring(m) + +def create_linux_bridge(bridge, interface): + m = E.interface( + E.start(mode='onboot'), + E.bridge( + E.interface( + type='ethernet', + name=interface)), + type='bridge', + name=bridge) + return ET.tostring(m) + -- 2.1.0

On Thu, Oct 29, 2015 at 9:24 PM, Ramon Medeiros <ramonn@linux.vnet.ibm.com> wrote:
Create linux-bridge with libvirt API. Kimchi was only creating macvtap devices, with has some limitation. For further information, take a look at Kimchi wiki discuss: https://github.com/kimchi-project/kimchi/wiki/Create-guest-network
Signed-off-by: Ramon Medeiros <ramonn@linux.vnet.ibm.com>
Testing:
In my case, i create a new bridge over the interface enp0s25 with name ramon
curl -u root -H "Content-Type: application/json" -H "Accept: application/json" "http://localhost:8010/plugins/kimchi/networks" -X POST -d '{"name": "ramon", "connection":"bridge", "interface":"enp0s25", "mode":"linux-bridge"}'
To delete, you can remove by UI or:
curl -u root -H "Content-Type: application/json" -H "Accept: application/json" "http://localhost:8010/plugins/kimchi/networks/ramon" -X DELETE -d '' --- src/wok/plugins/kimchi/model/networks.py | 35 +++++++++++++++++++++++++++--- src/wok/plugins/kimchi/network.py | 20 +++++++++++++++++ src/wok/plugins/kimchi/xmlutils/network.py | 12 ++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/src/wok/plugins/kimchi/model/networks.py b/src/wok/plugins/kimchi/model/networks.py index 71ea595..dc34f3f 100644 --- a/src/wok/plugins/kimchi/model/networks.py +++ b/src/wok/plugins/kimchi/model/networks.py @@ -35,10 +35,10 @@ from wok.plugins.kimchi import network as knetwork from wok.plugins.kimchi.osinfo import defaults as tmpl_defaults from wok.plugins.kimchi.xmlutils.network import create_vlan_tagged_bridge_xml from wok.plugins.kimchi.xmlutils.network import to_network_xml - +from wok.plugins.kimchi.xmlutils.network import create_linux_bridge
KIMCHI_BRIDGE_PREFIX = 'kb' - +IFCFG = "/etc/sysconfig/network-scripts/ifcfg-" That one wouldn't work on SUSE systems. We have /etc/sysconfig/network/ifcfg-br0
class NetworksModel(object): def __init__(self, **kargs): @@ -160,7 +160,10 @@ class NetworksModel(object): def _set_network_bridge(self, params): try: iface = params['interface'] - if iface in self.get_all_networks_interfaces(): + + if params["mode"] == "linux-bridge": + iface = self._create_linux_bridge(iface) + elif iface in self.get_all_networks_interfaces(): msg_args = {'iface': iface, 'network': params['name']} raise InvalidParameter("KCHNET0006E", msg_args) except KeyError: @@ -172,6 +175,7 @@ class NetworksModel(object): raise InvalidParameter('KCHNET0019E', {'name': iface}) params['bridge'] = iface elif netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface): + if params.get('vlan_id') is None: params['forward']['dev'] = iface else: @@ -196,6 +200,31 @@ class NetworksModel(object): net_dict['bridge'] and interfaces.append(net_dict['bridge']) return interfaces
+ def _create_linux_bridge(self, interface): + newBridge = KIMCHI_BRIDGE_PREFIX + interface[-8:] + bridges_list = knetwork.list_bridges() + + bridges = [] + for bridge in bridges_list: + bridges.append(bridge["bridge"]) + + # bridge already exists: create new name + if newBridge in bridges: + for i in range(0,10): + newBridge = KIMCHI_BRIDGE_PREFIX + interface[-7:] + str(i) + if newBridge not in bridges: + break + + # create linux bridge by libvirt + try: + conn = self.conn.get() + iface = conn.interfaceDefineXML(create_linux_bridge(newBridge, interface)) + iface.create() + except libvirt.libvirtError as e: + raise OperationFailed("KCHNET0008E", + {'name': newBridge, 'err': e.get_error_message()}) + return newBridge + def _create_vlan_tagged_bridge(self, interface, vlan_id): # Truncate the interface name if it exceeds 8 characters to make sure # the length of bridge name is less than 15 (its maximum value). diff --git a/src/wok/plugins/kimchi/network.py b/src/wok/plugins/kimchi/network.py index 1433b8a..4612599 100644 --- a/src/wok/plugins/kimchi/network.py +++ b/src/wok/plugins/kimchi/network.py @@ -20,7 +20,9 @@
import ethtool import ipaddr +import os
+from wok.utils import run_command
APrivateNets = ipaddr.IPNetwork("10.0.0.0/8") BPrivateNets = ipaddr.IPNetwork("172.16.0.0/12") @@ -60,3 +62,21 @@ def get_one_free_network(used_nets, nets_pool=PrivateNets): if net: return net return None + +def list_bridges(): + # get all bridges + _, err, rc = run_command(['brctl', 'show']) + output = _.splitlines() + + # iterate over output + i = 1 + bridges = [] + while (i < len(output)): + + # get bridge name + bridges.append({"bridge": output[i].split('\t')[0], + "interface": output[i].split('\t')[5]}) + i += 1 + + return bridges + diff --git a/src/wok/plugins/kimchi/xmlutils/network.py b/src/wok/plugins/kimchi/xmlutils/network.py index c73aad9..2fdf8d4 100644 --- a/src/wok/plugins/kimchi/xmlutils/network.py +++ b/src/wok/plugins/kimchi/xmlutils/network.py @@ -120,3 +120,15 @@ def create_vlan_tagged_bridge_xml(bridge, interface, vlan_id): type='bridge', name=bridge) return ET.tostring(m) + +def create_linux_bridge(bridge, interface): + m = E.interface( + E.start(mode='onboot'), + E.bridge( + E.interface( + type='ethernet', + name=interface)), + type='bridge', + name=bridge) + return ET.tostring(m) + -- 2.1.0
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

+IFCFG = "/etc/sysconfig/network-scripts/ifcfg-"
That one wouldn't work on SUSE systems. We have /etc/sysconfig/network/ifcfg-br0
Hi, i forgot to remove this constant. As you can see, the constant has no reference in the code. All bridge dealing are made by libvirt. -- Ramon Nunes Medeiros Kimchi Developer Linux Technology Center Brazil IBM Systems & Technology Group Phone : +55 19 2132 7878 ramonn@br.ibm.com
participants (2)
-
Dinar Valeev
-
Ramon Medeiros