summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2017-10-16 14:18:24 +0000
committerGerrit Code Review <review@openstack.org>2017-10-16 14:18:24 +0000
commit4188f679d898300004a88f1f83275afc63d23baa (patch)
tree59e4af0c4dd6bb4dd3e12ddee964fe9734736a47
parent1a19c820767d927aecd594ea0536202a4d3f3f9b (diff)
parent48e3f4f91d16aa518433e712469d82a8254146aa (diff)
Merge "Introduce a SR-IOV binding driver"
-rw-r--r--kuryr/lib/binding/__init__.py11
-rw-r--r--kuryr/lib/binding/drivers/hw_veb.py74
-rw-r--r--kuryr/lib/binding/drivers/ipvlan.py3
-rw-r--r--kuryr/lib/binding/drivers/macvlan.py3
-rw-r--r--kuryr/lib/binding/drivers/nested.py3
-rw-r--r--kuryr/lib/binding/drivers/veth.py8
-rw-r--r--kuryr/lib/binding/drivers/vlan.py3
-rw-r--r--kuryr/lib/constants.py1
-rw-r--r--kuryr/tests/unit/binding/drivers/test_hw_veb.py94
-rw-r--r--releasenotes/notes/bp-sriov-binding-7cebeae1c9f27ea4.yaml5
10 files changed, 194 insertions, 11 deletions
diff --git a/kuryr/lib/binding/__init__.py b/kuryr/lib/binding/__init__.py
index 8953b97..6834ef1 100644
--- a/kuryr/lib/binding/__init__.py
+++ b/kuryr/lib/binding/__init__.py
@@ -14,7 +14,7 @@ from oslo_utils import importutils
14 14
15 15
16def port_bind(endpoint_id, port, subnets, network=None, vm_port=None, 16def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
17 segmentation_id=None): 17 segmentation_id=None, **kwargs):
18 """Binds the Neutron port to the network interface on the host. 18 """Binds the Neutron port to the network interface on the host.
19 19
20 :param endpoint_id: the ID of the endpoint as string 20 :param endpoint_id: the ID of the endpoint as string
@@ -29,6 +29,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
29 port of a container which is running inside this Nova 29 port of a container which is running inside this Nova
30 instance (either ipvlan/macvlan or a subport). 30 instance (either ipvlan/macvlan or a subport).
31 :param segmentation_id: ID of the segment for container traffic isolation) 31 :param segmentation_id: ID of the segment for container traffic isolation)
32 :param kwargs: Additional driver-specific arguments
32 :returns: the tuple of the names of the veth pair and the tuple of stdout 33 :returns: the tuple of the names of the veth pair and the tuple of stdout
33 and stderr returned by processutils.execute invoked with the 34 and stderr returned by processutils.execute invoked with the
34 executable script for binding 35 executable script for binding
@@ -38,18 +39,20 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
38 driver = importutils.import_module(cfg.CONF.binding.driver) 39 driver = importutils.import_module(cfg.CONF.binding.driver)
39 return driver.port_bind(endpoint_id, port, subnets, network=network, 40 return driver.port_bind(endpoint_id, port, subnets, network=network,
40 vm_port=vm_port, 41 vm_port=vm_port,
41 segmentation_id=segmentation_id) 42 segmentation_id=segmentation_id,
43 **kwargs)
42 44
43 45
44def port_unbind(endpoint_id, neutron_port): 46def port_unbind(endpoint_id, neutron_port, **kwargs):
45 """Unbinds the Neutron port from the network interface on the host. 47 """Unbinds the Neutron port from the network interface on the host.
46 48
47 :param endpoint_id: the ID of the Docker container as string 49 :param endpoint_id: the ID of the Docker container as string
48 :param neutron_port: a port dictionary returned from python-neutronclient 50 :param neutron_port: a port dictionary returned from python-neutronclient
51 :param kwargs: Additional driver-specific arguments
49 :returns: the tuple of stdout and stderr returned by processutils.execute 52 :returns: the tuple of stdout and stderr returned by processutils.execute
50 invoked with the executable script for unbinding 53 invoked with the executable script for unbinding
51 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError 54 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
52 """ 55 """
53 driver = importutils.import_module(cfg.CONF.binding.driver) 56 driver = importutils.import_module(cfg.CONF.binding.driver)
54 57
55 return driver.port_unbind(endpoint_id, neutron_port) 58 return driver.port_unbind(endpoint_id, neutron_port, **kwargs)
diff --git a/kuryr/lib/binding/drivers/hw_veb.py b/kuryr/lib/binding/drivers/hw_veb.py
new file mode 100644
index 0000000..7188ac8
--- /dev/null
+++ b/kuryr/lib/binding/drivers/hw_veb.py
@@ -0,0 +1,74 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13from oslo_concurrency import processutils
14
15from kuryr.lib.binding.drivers import utils
16from kuryr.lib import constants
17
18
19def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
20 segmentation_id=None, **kwargs):
21 """Binds the Neutron port to the network interface on the host.
22
23 :param endpoint_id: the ID of the endpoint as string
24 :param port: the container Neutron port dictionary as returned by
25 python-neutronclient
26 :param subnets: an iterable of all the Neutron subnets which the
27 endpoint is trying to join
28 :param network: the Neutron network which the endpoint is trying to
29 join
30 :param vm_port: the Nova instance port dictionary, as returned by
31 python-neutronclient. Container port under binding is
32 running inside this instance (either ipvlan/macvlan or
33 a subport)
34 :param segmentation_id: ID of the segment for container traffic isolation)
35 :param kwargs: Additional driver-specific arguments
36 :returns: the tuple of the names of the veth pair and the tuple of stdout
37 and stderr returned by processutils.execute invoked with the
38 executable script for binding
39 :raises: kuryr.common.exceptions.VethCreationFailure,
40 processutils.ProcessExecutionError
41 """
42 pf_ifname = kwargs['pf_ifname']
43 vf_num = kwargs['vf_num']
44 mac_addr = port[utils.MAC_ADDRESS_KEY]
45 vlan = port[constants.VIF_DETAILS_KEY][constants.VIF_DETAILS_VLAN_KEY]
46 _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr, vlan)
47 return None, None, ('', None)
48
49
50def port_unbind(endpoint_id, neutron_port, **kwargs):
51 """Unbinds the Neutron port from the network interface on the host.
52
53 :param endpoint_id: the ID of the Docker container as string
54 :param neutron_port: a port dictionary returned from python-neutronclient
55 :param kwargs: Additional driver-specific arguments
56 :returns: the tuple of stdout and stderr returned by processutils.execute
57 invoked with the executable script for unbinding
58 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
59 """
60 pf_ifname = kwargs['pf_ifname']
61 vf_num = kwargs['vf_num']
62 mac_addr = neutron_port[utils.MAC_ADDRESS_KEY]
63 _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr)
64 return '', None
65
66
67def _set_vf_interface_vlan(pf_ifname, vf_num, mac_addr, vlan=0):
68 exit_code = [0, 2, 254]
69 processutils.execute('ip', 'link', 'set', pf_ifname,
70 'vf', vf_num,
71 'mac', mac_addr,
72 'vlan', vlan,
73 run_as_root=True,
74 check_exit_code=exit_code)
diff --git a/kuryr/lib/binding/drivers/ipvlan.py b/kuryr/lib/binding/drivers/ipvlan.py
index a76e6dc..43e7122 100644
--- a/kuryr/lib/binding/drivers/ipvlan.py
+++ b/kuryr/lib/binding/drivers/ipvlan.py
@@ -21,7 +21,7 @@ IPVLAN_MODE_L2 = ifinfmsg.ifinfo.data_map['ipvlan'].modes['IPVLAN_MODE_L2']
21 21
22 22
23def port_bind(endpoint_id, port, subnets, network=None, vm_port=None, 23def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
24 segmentation_id=None): 24 segmentation_id=None, **kwargs):
25 """Binds the Neutron port to the network interface on the host. 25 """Binds the Neutron port to the network interface on the host.
26 26
27 :param endpoint_id: the ID of the endpoint as string 27 :param endpoint_id: the ID of the endpoint as string
@@ -35,6 +35,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
35 python-neutronclient. Container is running inside 35 python-neutronclient. Container is running inside
36 this instance (either ipvlan/macvlan or a subport) 36 this instance (either ipvlan/macvlan or a subport)
37 :param segmentation_id: ID of the segment for container traffic isolation) 37 :param segmentation_id: ID of the segment for container traffic isolation)
38 :param kwargs: Additional driver-specific arguments
38 :returns: the tuple of the names of the veth pair and the tuple of stdout 39 :returns: the tuple of the names of the veth pair and the tuple of stdout
39 and stderr returned by processutils.execute invoked with the 40 and stderr returned by processutils.execute invoked with the
40 executable script for binding 41 executable script for binding
diff --git a/kuryr/lib/binding/drivers/macvlan.py b/kuryr/lib/binding/drivers/macvlan.py
index c0fbe0e..7d005fd 100644
--- a/kuryr/lib/binding/drivers/macvlan.py
+++ b/kuryr/lib/binding/drivers/macvlan.py
@@ -20,7 +20,7 @@ MACVLAN_MODE_BRIDGE = 'bridge'
20 20
21 21
22def port_bind(endpoint_id, port, subnets, network=None, vm_port=None, 22def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
23 segmentation_id=None): 23 segmentation_id=None, **kwargs):
24 """Binds the Neutron port to the network interface on the host. 24 """Binds the Neutron port to the network interface on the host.
25 25
26 :param endpoint_id: the ID of the endpoint as string 26 :param endpoint_id: the ID of the endpoint as string
@@ -34,6 +34,7 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
34 python-neutronclient. Container is running inside 34 python-neutronclient. Container is running inside
35 instance. 35 instance.
36 :param segmentation_id: ID of the segment for container traffic isolation) 36 :param segmentation_id: ID of the segment for container traffic isolation)
37 :param kwargs: Additional driver-specific arguments
37 :returns: the tuple of the names of the veth pair and the tuple of stdout 38 :returns: the tuple of the names of the veth pair and the tuple of stdout
38 and stderr returned by processutils.execute invoked with the 39 and stderr returned by processutils.execute invoked with the
39 executable script for binding 40 executable script for binding
diff --git a/kuryr/lib/binding/drivers/nested.py b/kuryr/lib/binding/drivers/nested.py
index 3213e6d..3604cdd 100644
--- a/kuryr/lib/binding/drivers/nested.py
+++ b/kuryr/lib/binding/drivers/nested.py
@@ -31,11 +31,12 @@ def get_link_iface(port):
31 return link 31 return link
32 32
33 33
34def port_unbind(endpoint_id, neutron_port): 34def port_unbind(endpoint_id, neutron_port, **kwargs):
35 """Unbinds the Neutron port from the network interface on the host. 35 """Unbinds the Neutron port from the network interface on the host.
36 36
37 :param endpoint_id: the ID of the Docker container as string 37 :param endpoint_id: the ID of the Docker container as string
38 :param neutron_port: a port dictionary returned from python-neutronclient 38 :param neutron_port: a port dictionary returned from python-neutronclient
39 :param kwargs: Additional driver-specific arguments
39 :returns: the tuple of stdout and stderr returned by processutils.execute 40 :returns: the tuple of stdout and stderr returned by processutils.execute
40 invoked with the executable script for unbinding 41 invoked with the executable script for unbinding
41 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError 42 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
diff --git a/kuryr/lib/binding/drivers/veth.py b/kuryr/lib/binding/drivers/veth.py
index 9f79d1e..778b9a3 100644
--- a/kuryr/lib/binding/drivers/veth.py
+++ b/kuryr/lib/binding/drivers/veth.py
@@ -27,7 +27,7 @@ KIND = 'veth'
27 27
28 28
29def port_bind(endpoint_id, port, subnets, network=None, vm_port=None, 29def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
30 segmentation_id=None): 30 segmentation_id=None, **kwargs):
31 """Binds the Neutron port to the network interface on the host. 31 """Binds the Neutron port to the network interface on the host.
32 32
33 :param endpoint_id: the ID of the endpoint as string 33 :param endpoint_id: the ID of the endpoint as string
@@ -37,11 +37,12 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
37 endpoint is trying to join 37 endpoint is trying to join
38 :param network: the Neutron network which the endpoint is trying to 38 :param network: the Neutron network which the endpoint is trying to
39 join 39 join
40 :param vm_port: the Nova instance dictionary, as returned by 40 :param vm_port: the Nova instance port dictionary, as returned by
41 python-neutronclient. Container port under binding is 41 python-neutronclient. Container port under binding is
42 running inside this instance (either ipvlan/macvlan or 42 running inside this instance (either ipvlan/macvlan or
43 a subport) 43 a subport)
44 :param segmentation_id: ID of the segment for container traffic isolation) 44 :param segmentation_id: ID of the segment for container traffic isolation)
45 :param kwargs: Additional driver-specific arguments
45 :returns: the tuple of the names of the veth pair and the tuple of stdout 46 :returns: the tuple of the names of the veth pair and the tuple of stdout
46 and stderr returned by processutils.execute invoked with the 47 and stderr returned by processutils.execute invoked with the
47 executable script for binding 48 executable script for binding
@@ -84,11 +85,12 @@ def port_bind(endpoint_id, port, subnets, network=None, vm_port=None,
84 return host_ifname, container_ifname, (stdout, stderr) 85 return host_ifname, container_ifname, (stdout, stderr)
85 86
86 87
87def port_unbind(endpoint_id, neutron_port): 88def port_unbind(endpoint_id, neutron_port, **kwargs):
88 """Unbinds the Neutron port from the network interface on the host. 89 """Unbinds the Neutron port from the network interface on the host.
89 90
90 :param endpoint_id: the ID of the Docker container as string 91 :param endpoint_id: the ID of the Docker container as string
91 :param neutron_port: a port dictionary returned from python-neutronclient 92 :param neutron_port: a port dictionary returned from python-neutronclient
93 :param kwargs: Additional driver-specific arguments
92 :returns: the tuple of stdout and stderr returned by processutils.execute 94 :returns: the tuple of stdout and stderr returned by processutils.execute
93 invoked with the executable script for unbinding 95 invoked with the executable script for unbinding
94 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError 96 :raises: processutils.ProcessExecutionError, pyroute2.NetlinkError
diff --git a/kuryr/lib/binding/drivers/vlan.py b/kuryr/lib/binding/drivers/vlan.py
index 7fa470d..680b99a 100644
--- a/kuryr/lib/binding/drivers/vlan.py
+++ b/kuryr/lib/binding/drivers/vlan.py
@@ -18,7 +18,7 @@ KIND = 'vlan'
18 18
19 19
20def port_bind(endpoint_id, port, subnets, network=None, 20def port_bind(endpoint_id, port, subnets, network=None,
21 vm_port=None, segmentation_id=None): 21 vm_port=None, segmentation_id=None, **kwargs):
22 """Binds the Neutron port to the network interface on the host. 22 """Binds the Neutron port to the network interface on the host.
23 23
24 :param endpoint_id: the ID of the endpoint as string 24 :param endpoint_id: the ID of the endpoint as string
@@ -32,6 +32,7 @@ def port_bind(endpoint_id, port, subnets, network=None,
32 python-neutronclient. Container is running inside this 32 python-neutronclient. Container is running inside this
33 instance (either ipvlan/macvlan or a subport) 33 instance (either ipvlan/macvlan or a subport)
34 :param segmentation_id: ID of the segment for container traffic isolation) 34 :param segmentation_id: ID of the segment for container traffic isolation)
35 :param kwargs: Additional driver-specific arguments
35 :returns: the tuple of the names of the veth pair and the tuple of stdout 36 :returns: the tuple of the names of the veth pair and the tuple of stdout
36 and stderr returned by processutils.execute invoked with the 37 and stderr returned by processutils.execute invoked with the
37 executable script for binding 38 executable script for binding
diff --git a/kuryr/lib/constants.py b/kuryr/lib/constants.py
index 25c9559..06a306d 100644
--- a/kuryr/lib/constants.py
+++ b/kuryr/lib/constants.py
@@ -28,4 +28,5 @@ DEFAULT_NETWORK_MTU = 1500
28FALLBACK_VIF_TYPE = 'unbound' 28FALLBACK_VIF_TYPE = 'unbound'
29UNBINDING_SUBCOMMAND = 'unbind' 29UNBINDING_SUBCOMMAND = 'unbind'
30VIF_DETAILS_KEY = 'binding:vif_details' 30VIF_DETAILS_KEY = 'binding:vif_details'
31VIF_DETAILS_VLAN_KEY = 'vlan'
31VIF_TYPE_KEY = 'binding:vif_type' 32VIF_TYPE_KEY = 'binding:vif_type'
diff --git a/kuryr/tests/unit/binding/drivers/test_hw_veb.py b/kuryr/tests/unit/binding/drivers/test_hw_veb.py
new file mode 100644
index 0000000..447d204
--- /dev/null
+++ b/kuryr/tests/unit/binding/drivers/test_hw_veb.py
@@ -0,0 +1,94 @@
1# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13
14import mock
15from oslo_utils import uuidutils
16
17from kuryr.lib.binding.drivers import hw_veb
18from kuryr.lib import constants
19from kuryr.lib import utils
20from kuryr.tests.unit import base
21
22
23mock_create = mock.MagicMock()
24mock_interface = mock.MagicMock()
25
26
27class TestHwVebDriver(base.TestCase):
28 """Unit tests for hw_veb driver"""
29
30 @mock.patch('oslo_concurrency.processutils.execute',
31 return_value=('fake_stdout', 'fake_stderr'))
32 def test_port_bind(self, mock_execute):
33 fake_docker_endpoint_id = utils.get_hash()
34 fake_docker_network_id = utils.get_hash()
35 fake_port_id = uuidutils.generate_uuid()
36 fake_neutron_v4_subnet_id = uuidutils.generate_uuid()
37 fake_neutron_v6_subnet_id = uuidutils.generate_uuid()
38 fake_vlan_id = 100
39 fake_vif_details = {constants.VIF_DETAILS_VLAN_KEY: fake_vlan_id}
40 fake_vif_type = "ovs"
41 fake_port = self._get_fake_port(
42 fake_docker_endpoint_id, fake_docker_network_id,
43 fake_port_id, constants.PORT_STATUS_ACTIVE,
44 fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id,
45 vif_details=fake_vif_details, vif_type=fake_vif_type)
46 fake_subnets = self._get_fake_subnets(
47 fake_docker_endpoint_id, fake_docker_network_id,
48 fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id)
49 fake_network = self._get_fake_networks(fake_docker_network_id)
50 fake_pf_ifname = 'eth13'
51 fake_vf_num = 1
52
53 hw_veb.port_bind(fake_docker_endpoint_id,
54 fake_port['port'],
55 fake_subnets['subnets'],
56 fake_network['networks'][0],
57 pf_ifname=fake_pf_ifname,
58 vf_num=fake_vf_num)
59
60 mock_execute.assert_called_once_with(
61 'ip', 'link', 'set', fake_pf_ifname,
62 'vf', fake_vf_num,
63 'mac', fake_port['port']['mac_address'],
64 'vlan', fake_vlan_id,
65 run_as_root=True,
66 check_exit_code=[0, 2, 254])
67
68 @mock.patch('oslo_concurrency.processutils.execute',
69 return_value=('fake_stdout', 'fake_stderr'))
70 def test_port_unbind(self, mock_execute):
71 fake_docker_endpoint_id = utils.get_hash()
72 fake_docker_network_id = utils.get_hash()
73 fake_port_id = uuidutils.generate_uuid()
74 fake_neutron_v4_subnet_id = uuidutils.generate_uuid()
75 fake_neutron_v6_subnet_id = uuidutils.generate_uuid()
76 fake_vif_type = "ovs"
77 fake_port = self._get_fake_port(
78 fake_docker_endpoint_id, fake_docker_network_id,
79 fake_port_id, constants.PORT_STATUS_ACTIVE,
80 fake_neutron_v4_subnet_id, fake_neutron_v6_subnet_id,
81 vif_type=fake_vif_type)
82 fake_pf_ifname = 'eth13'
83 fake_vf_num = 1
84 hw_veb.port_unbind(fake_docker_endpoint_id, fake_port['port'],
85 pf_ifname=fake_pf_ifname,
86 vf_num=fake_vf_num)
87 mock_execute.assert_called_once()
88 mock_execute.assert_called_once_with(
89 'ip', 'link', 'set', fake_pf_ifname,
90 'vf', fake_vf_num,
91 'mac', fake_port['port']['mac_address'],
92 'vlan', 0,
93 run_as_root=True,
94 check_exit_code=[0, 2, 254])
diff --git a/releasenotes/notes/bp-sriov-binding-7cebeae1c9f27ea4.yaml b/releasenotes/notes/bp-sriov-binding-7cebeae1c9f27ea4.yaml
new file mode 100644
index 0000000..7f7de0a
--- /dev/null
+++ b/releasenotes/notes/bp-sriov-binding-7cebeae1c9f27ea4.yaml
@@ -0,0 +1,5 @@
1---
2features:
3 - |
4 Introduce hw_veb binding driver. This driver can perform binding
5 of SR-IOV neutron port.