On 30/10/2015 14:29, Ramon Medeiros 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(a)linux.vnet.ibm.com>
Changes:
v2:
Remove unused imports and constants
Fix pep8 issues
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"}'
From what I remembered from the RFC, we have agreed to do not add a new
parameter "mode" and instead of that use "connection" equal to
"macvtap"
for macvtap bridge or "bridge" for Linux bridge.
Any special reason to do not follow the RFC discussion?
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 | 19 ++++++++++++++++
src/wok/plugins/kimchi/xmlutils/network.py | 12 ++++++++++
3 files changed, 64 insertions(+), 2 deletions(-)
Please, update API.json, docs/API.md and add test cases to cover the new
API.
diff --git a/src/wok/plugins/kimchi/model/networks.py
b/src/wok/plugins/kimchi/model/networks.py
index 71ea595..c17a3bf 100644
--- a/src/wok/plugins/kimchi/model/networks.py
+++ b/src/wok/plugins/kimchi/model/networks.py
@@ -30,12 +30,13 @@ from wok.rollbackcontext import RollbackContext
from wok.utils import run_command, wok_log
from wok.xmlutils.utils import xpath_get_text
+
Just one line to separated import blocks.
from wok.plugins.kimchi import netinfo
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'
@@ -160,7 +161,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)
Don't you need to verify the interface is not in use by any other network?
+ elif iface in self.get_all_networks_interfaces():
msg_args = {'iface': iface, 'network':
params['name']}
raise InvalidParameter("KCHNET0006E", msg_args)
except KeyError:
@@ -196,6 +200,33 @@ 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
+
What happen when you are not able to get a bridge name?
+ # 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..18df281 100644
--- a/src/wok/plugins/kimchi/network.py
+++ b/src/wok/plugins/kimchi/network.py
@@ -21,6 +21,7 @@
import ethtool
import ipaddr
+from wok.utils import run_command
APrivateNets = ipaddr.IPNetwork("10.0.0.0/8")
BPrivateNets = ipaddr.IPNetwork("172.16.0.0/12")
@@ -60,3 +61,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):
create_linux_bridge_xml is more meaningful for this function
+ m = E.interface(
+ E.start(mode='onboot'),
+ E.bridge(
+ E.interface(
+ type='ethernet',
+ name=interface)),
+ type='bridge',
+ name=bridge)
+ return ET.tostring(m)
+