[PATCH v3] [Kimchi 0/3] Implementing 'Passthrough' virtual network type

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> v3: - overhaul. Implemented as a new network type instead of a variation of the 'macvtap' type. - passthrough networks now accepts multiple interfaces like VEPA does v2: - used interface now being displayed in UI and backend - fixed an issue where the newly created network would appear as 'passthrough' in the UI until a page refresh This patch set adds a new network type called 'passthrough' to Kimchi. Docs, model, test and UI changes included. This is how it works in action using curl: $ curl -k -u root -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'https://localhost:10001/plugins/kimchi/networks' -d'{"name":"danielhb_passthrough", "connection":"passthrough", "interfaces":["enP2p1s0","enP2p1s1f2"]}' Enter host password for user 'root': { "subnet":"", "connection":"passthrough", "state":"inactive", "name":"danielhb_passthrough", "autostart":true, "in_use":false, "dhcp":{ "start":"", "end":"" }, "interfaces":[ "enP2p1s0", "enP2p1s1f2" ], "vms":[], "persistent":true } Daniel Henrique Barboza (3): Passthrough macvtap network support: doc changes Passthrough macvtap network support: model and test changes Passthrough macvtap network support: UI changes API.json | 2 +- docs/API.md | 8 +++++++ i18n.py | 2 +- model/networks.py | 15 +++++++------ tests/test_networkxml.py | 42 ++++++++++++++++++++++++++++++++++++ ui/js/src/kimchi.network.js | 1 + ui/js/src/kimchi.network_add_main.js | 23 +++++++++++++------- ui/pages/network-add.html.tmpl | 1 + xmlutils/network.py | 2 +- 9 files changed, 79 insertions(+), 17 deletions(-) -- 2.5.5

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> This patch makes changes in docs/API.md, API.json and i18n.py to add a new libvirt network mode called 'passthrough'. This new network type works as a direct macvtap network that assigns a physical device in passthrough mode. Only one physical is allowed for each VM. It also allows for multiple interfaces, similar as the current VEPA network implementation does while libvirt controls the availability of the devices. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- API.json | 2 +- docs/API.md | 8 ++++++++ i18n.py | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/API.json b/API.json index 40278bb..8d4f725 100644 --- a/API.json +++ b/API.json @@ -376,7 +376,7 @@ "connection": { "description": "Specifies how this network should be connected to the other networks", "type": "string", - "pattern": "^isolated|nat|bridge|macvtap|vepa$", + "pattern": "^isolated|nat|bridge|macvtap|vepa|passthrough$", "required": true, "error": "KCHNET0012E" }, diff --git a/docs/API.md b/docs/API.md index 83f9d38..7072ab2 100644 --- a/docs/API.md +++ b/docs/API.md @@ -692,6 +692,14 @@ A interface represents available interface on host. specified interface. * vepa: All traffic will be forward to one or more physical devices directly connected to a VEPA-enabled switch. + * passthrough: A connection of this type uses a "direct" connection in + "passthrough" mode to connect each guest to the network. + Each guest will use one of the available physical + devices included in this network. Only one device can + be used for each guest - libvirt will keep track of which + interfaces are in use. Thus, a network of type 'passthrough' + with N devices will support the maximum of N guests + running at the same time. * bridge: All traffic on this network will be bridged through a Linux bridged, which is created upon specified interface in case it is not already a Linux bridge. diff --git a/i18n.py b/i18n.py index cfbc81e..1fb128b 100644 --- a/i18n.py +++ b/i18n.py @@ -263,7 +263,7 @@ messages = { "KCHNET0009E": _("Unable to find a free IP address for network '%(name)s'"), "KCHNET0010E": _("The interface %(iface)s already exists."), "KCHNET0011E": _("Network name must be a string without slashes (/) or quotes (\")"), - "KCHNET0012E": _("Supported network types are isolated, NAT, macvtap, bridge and vepa"), + "KCHNET0012E": _("Supported network types are isolated, NAT, macvtap, bridge, vepa and passthrough."), "KCHNET0013E": _("Network subnet must be a string with IP address and prefix or netmask"), "KCHNET0014E": _("Network interfaces must be an array."), "KCHNET0015E": _("Network VLAN ID must be an integer between 1 and 4094"), -- 2.5.5

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> Adding support for the new network type 'passthrough'. The way it is supported in model and XML files is similar to what we already do in the VEPA network. New unit tests included. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- model/networks.py | 15 +++++++++------ tests/test_networkxml.py | 42 ++++++++++++++++++++++++++++++++++++++++++ xmlutils/network.py | 2 +- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/model/networks.py b/model/networks.py index cc59ca8..e04c8e4 100644 --- a/model/networks.py +++ b/model/networks.py @@ -102,8 +102,8 @@ class NetworksModel(object): self._set_network_macvtap(params) elif connection == 'bridge': self._set_network_bridge(params) - elif connection == 'vepa': - self._set_network_vepa(params) + elif connection in ['passthrough', 'vepa']: + self._set_network_multiple_interfaces(params) # create network XML xml = to_network_xml(**params) @@ -194,13 +194,16 @@ class NetworksModel(object): # set macvtap network params['forward'] = {'mode': 'bridge', 'dev': iface} - def _set_network_vepa(self, params): + def _set_network_multiple_interfaces(self, params): for iface in params['interfaces']: if ('vlan_id' in params or not (netinfo.is_bare_nic(iface) or netinfo.is_bonding(iface))): raise InvalidParameter('KCHNET0028E', {'name': iface}) - params['forward'] = {'mode': 'vepa', 'devs': params['interfaces']} + params['forward'] = { + 'mode': params["connection"], + 'devs': params['interfaces'] + } def _set_network_bridge(self, params): params['forward'] = {'mode': 'bridge'} @@ -369,7 +372,7 @@ class NetworkModel(object): subnet = ipaddr.IPNetwork(subnet) subnet = "%s/%s" % (subnet.network, subnet.prefixlen) - if connection == 'vepa': + if connection in ['passthrough', 'vepa']: interfaces = xpath_get_text( xml, "/network/forward/interface/@dev" @@ -509,7 +512,7 @@ class NetworkModel(object): # validate update parameters connection = info['connection'] - if connection in ['bridge', 'macvtap', 'vepa']: + if connection in ['bridge', 'macvtap', 'passthrough', 'vepa']: if params.get('subnet'): raise InvalidParameter("KCHNET0031E") elif connection in ['nat', 'isolated']: diff --git a/tests/test_networkxml.py b/tests/test_networkxml.py index 8e83744..a39cd61 100644 --- a/tests/test_networkxml.py +++ b/tests/test_networkxml.py @@ -195,6 +195,48 @@ class NetworkXmlTests(unittest.TestCase): xml_str = nxml.to_network_xml(**params) self.assertEqual(xml_str, expected_xml) + def test_passthrough_network_singledev_xml(self): + expected_xml = """<network>\ +<name>test_passthrough</name>\ +<forward mode="passthrough" dev="passthrough_interface">\ +<interface dev="passthrough_interface"/>\ +</forward>\ +</network>""" + + params = { + "name": "test_passthrough", + "forward": { + "mode": "passthrough", + "devs": ["passthrough_interface"] + } + } + xml_str = nxml.to_network_xml(**params) + self.assertEqual(xml_str, expected_xml) + + def test_passthrough_network_multipledevs_xml(self): + expected_xml = """<network>\ +<name>test_passthrough</name>\ +<forward mode="passthrough" dev="passthrough_interface1">\ +<interface dev="passthrough_interface1"/>\ +<interface dev="passthrough_interface2"/>\ +<interface dev="passthrough_interface3"/>\ +</forward>\ +</network>""" + + params = { + "name": "test_passthrough", + "forward": { + "mode": "passthrough", + "devs": [ + "passthrough_interface1", + "passthrough_interface2", + "passthrough_interface3" + ] + } + } + xml_str = nxml.to_network_xml(**params) + self.assertEqual(xml_str, expected_xml) + class InterfaceXmlTests(unittest.TestCase): diff --git a/xmlutils/network.py b/xmlutils/network.py index b35f65a..2e2966b 100644 --- a/xmlutils/network.py +++ b/xmlutils/network.py @@ -79,7 +79,7 @@ def _get_forward_elem(**kwargs): forward = E.forward() if 'mode' in kwargs.keys(): forward.set('mode', kwargs['mode']) - if kwargs['mode'] == 'vepa': + if kwargs['mode'] in ['passthrough', 'vepa']: devs = kwargs['devs'] forward.set('dev', devs[0]) -- 2.5.5

From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> UI changes to support the new network type 'passthrough'. Signed-off-by: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com> --- ui/js/src/kimchi.network.js | 1 + ui/js/src/kimchi.network_add_main.js | 23 +++++++++++++++-------- ui/pages/network-add.html.tmpl | 1 + 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/ui/js/src/kimchi.network.js b/ui/js/src/kimchi.network.js index d362010..c0100cf 100644 --- a/ui/js/src/kimchi.network.js +++ b/ui/js/src/kimchi.network.js @@ -17,6 +17,7 @@ */ kimchi.NETWORK_TYPE_MACVTAP = "macvtap"; +kimchi.NETWORK_TYPE_PASSTHROUGH = "passthrough"; kimchi.NETWORK_TYPE_BRIDGED = "bridge"; kimchi.NETWORK_TYPE_VEPA = "vepa"; diff --git a/ui/js/src/kimchi.network_add_main.js b/ui/js/src/kimchi.network_add_main.js index e12f1df..3090aeb 100644 --- a/ui/js/src/kimchi.network_add_main.js +++ b/ui/js/src/kimchi.network_add_main.js @@ -35,8 +35,10 @@ kimchi.startNetworkCreation = function() { interfaces: [ network.interface ], vlan_id: network.vlan_id }; - // in VEPA connection case, network.interface is already an array - if (data.connection === kimchi.NETWORK_TYPE_VEPA) { + // in PASSTHROUGH and VEPA connection case, + // network.interface is already an array + if (data.connection === kimchi.NETWORK_TYPE_PASSTHROUGH || + data.connection === kimchi.NETWORK_TYPE_VEPA ) { data.interfaces = network.interface; } @@ -86,7 +88,9 @@ kimchi.getNetworkDialogValues = function() { name : $("#networkName").val(), type : $("#networkType").val() }; - if (network.type === kimchi.NETWORK_TYPE_MACVTAP || network.type === kimchi.NETWORK_TYPE_VEPA) { + if (network.type === kimchi.NETWORK_TYPE_MACVTAP || + network.type === kimchi.NETWORK_TYPE_PASSTHROUGH || + network.type === kimchi.NETWORK_TYPE_VEPA) { network.interface = $("#networkDestinationID").val(); } if (network.type === kimchi.NETWORK_TYPE_BRIDGED) { @@ -110,16 +114,19 @@ kimchi.setupNetworkFormEvent = function() { $('#networkType').on('change', function() { var selectedType = $("#networkType").val(); - if(selectedType === kimchi.NETWORK_TYPE_MACVTAP || selectedType === kimchi.NETWORK_TYPE_VEPA) { - if (selectedType === kimchi.NETWORK_TYPE_VEPA){ + if(selectedType === kimchi.NETWORK_TYPE_MACVTAP || + selectedType === kimchi.NETWORK_TYPE_PASSTHROUGH || + selectedType === kimchi.NETWORK_TYPE_VEPA) { + + if (selectedType === kimchi.NETWORK_TYPE_MACVTAP) { + $('#networkDestinationID').attr('multiple', false).data('liveSearch',false); + } + else { $('#networkDestinationID').attr('multiple', true); if($('#networkDestinationID option').length > 10 ) { $('#networkDestinationID').data('liveSearch',true); } } - else { - $('#networkDestinationID').attr('multiple', false).data('liveSearch',false); - } $('#networkDestinationID').selectpicker('destroy'); kimchi.loadInterfaces(new Array("nic", "bonding")); } else { diff --git a/ui/pages/network-add.html.tmpl b/ui/pages/network-add.html.tmpl index 7a2fadb..fbbea3d 100644 --- a/ui/pages/network-add.html.tmpl +++ b/ui/pages/network-add.html.tmpl @@ -41,6 +41,7 @@ <option value="isolated">$_("Isolated: no external network connection")</option> <option value="nat">$_("NAT: outbound physical network connection only")</option> <option value="macvtap">$_("Macvtap: Virtual machines are connected to physical network directly")</option> + <option value="passthrough">$_("Passthrough: Virtual machines are connected using a macvtap connection in passthrough mode.")</option> <option value="vepa">$_("VEPA: special mode where virtual machines are connected to a VEPA-enabled switch")</option> <option value="bridge">$_("Bridged: Virtual machines are connected through a network bridge")</option> </select> -- 2.5.5

Reviewed-by: Socorro Stoppler <socorro@linux.vnet.ibm.com> Tested-by: Socorro Stoppler <socorro@linux.vnet.ibm.com> BTW, only reviewed UI code :) On 05/19/2016 08:31 AM, dhbarboza82@gmail.com wrote:
From: Daniel Henrique Barboza <danielhb@linux.vnet.ibm.com>
v3: - overhaul. Implemented as a new network type instead of a variation of the 'macvtap' type. - passthrough networks now accepts multiple interfaces like VEPA does
v2: - used interface now being displayed in UI and backend - fixed an issue where the newly created network would appear as 'passthrough' in the UI until a page refresh
This patch set adds a new network type called 'passthrough' to Kimchi. Docs, model, test and UI changes included.
This is how it works in action using curl:
$ curl -k -u root -H "Content-Type: application/json" -H "Accept: application/json" -X POST 'https://localhost:10001/plugins/kimchi/networks' -d'{"name":"danielhb_passthrough", "connection":"passthrough", "interfaces":["enP2p1s0","enP2p1s1f2"]}' Enter host password for user 'root': { "subnet":"", "connection":"passthrough", "state":"inactive", "name":"danielhb_passthrough", "autostart":true, "in_use":false, "dhcp":{ "start":"", "end":"" }, "interfaces":[ "enP2p1s0", "enP2p1s1f2" ], "vms":[], "persistent":true }
Daniel Henrique Barboza (3): Passthrough macvtap network support: doc changes Passthrough macvtap network support: model and test changes Passthrough macvtap network support: UI changes
API.json | 2 +- docs/API.md | 8 +++++++ i18n.py | 2 +- model/networks.py | 15 +++++++------ tests/test_networkxml.py | 42 ++++++++++++++++++++++++++++++++++++ ui/js/src/kimchi.network.js | 1 + ui/js/src/kimchi.network_add_main.js | 23 +++++++++++++------- ui/pages/network-add.html.tmpl | 1 + xmlutils/network.py | 2 +- 9 files changed, 79 insertions(+), 17 deletions(-)
participants (3)
-
Aline Manera
-
dhbarboza82@gmail.com
-
Socorro Stoppler