From 7e4517087ec0fea67aa9c080c47d71754efd805a Mon Sep 17 00:00:00 2001 From: Tabitha Date: Wed, 11 Nov 2020 04:40:20 +0100 Subject: [PATCH] Support for bulk port tagging extension With the recent support added to Neutron to allow adding a tag to multiple Ports at one call, this change stops Kuryr from performing two separate requests to create the Ports and then Tagging them and just does it one request. Change-Id: I09496a9cd9cce4c3ae2c6a75c242aa46fa79a07d Closes-Bug: #1899028 --- .../controller/drivers/nested_macvlan_vif.py | 3 ++- .../controller/drivers/nested_vlan_vif.py | 18 ++++++++++--- .../controller/drivers/neutron_vif.py | 25 +++++++++++++++++-- kuryr_kubernetes/controller/drivers/sriov.py | 10 +++++++- kuryr_kubernetes/controller/drivers/utils.py | 12 +++++++++ .../drivers/test_nested_macvlan_vif.py | 3 +++ .../drivers/test_nested_vlan_vif.py | 7 ++++++ .../controller/drivers/test_neutron_vif.py | 9 +++++++ .../unit/controller/drivers/test_sriov.py | 1 + .../controller/handlers/test_kuryrport.py | 2 ++ 10 files changed, 82 insertions(+), 8 deletions(-) diff --git a/kuryr_kubernetes/controller/drivers/nested_macvlan_vif.py b/kuryr_kubernetes/controller/drivers/nested_macvlan_vif.py index f7dd623fc..65c5d917a 100755 --- a/kuryr_kubernetes/controller/drivers/nested_macvlan_vif.py +++ b/kuryr_kubernetes/controller/drivers/nested_macvlan_vif.py @@ -47,7 +47,8 @@ class NestedMacvlanPodVIFDriver(nested_vif.NestedPodVIFDriver): if not container_port: container_port = os_net.create_port(**req) self._check_port_binding([container_port]) - utils.tag_neutron_resources([container_port]) + if not self._tag_on_creation: + utils.tag_neutron_resources([container_port]) container_mac = container_port.mac_address container_ips = frozenset(entry['ip_address'] for entry in diff --git a/kuryr_kubernetes/controller/drivers/nested_vlan_vif.py b/kuryr_kubernetes/controller/drivers/nested_vlan_vif.py index a66fa948c..3eb7b98a9 100644 --- a/kuryr_kubernetes/controller/drivers/nested_vlan_vif.py +++ b/kuryr_kubernetes/controller/drivers/nested_vlan_vif.py @@ -17,6 +17,7 @@ from kuryr.lib import constants as kl_const from kuryr.lib import exceptions as kl_exc from kuryr.lib import segmentation_type_drivers as seg_driver from openstack import exceptions as os_exc +from oslo_config import cfg from oslo_log import log as logging from kuryr_kubernetes import clients @@ -33,6 +34,8 @@ LOG = logging.getLogger(__name__) DEFAULT_MAX_RETRY_COUNT = 3 DEFAULT_RETRY_INTERVAL = 1 +CONF = cfg.CONF + class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): """Manages ports for nested-containers using VLANs to provide VIFs.""" @@ -45,7 +48,8 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): rq = self._get_port_request(pod, project_id, subnets, security_groups) port = os_net.create_port(**rq) self._check_port_binding([port]) - utils.tag_neutron_resources([port]) + if not self._tag_on_creation: + utils.tag_neutron_resources([port]) vlan_id = self._add_subport(trunk_id, port.id) return ovu.neutron_to_osvif_vif_nested_vlan(port, subnets, vlan_id) @@ -87,7 +91,8 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): LOG.exception("Error creating bulk ports: %s", bulk_port_rq) raise self._check_port_binding(ports) - utils.tag_neutron_resources(ports) + if not self._tag_on_creation: + utils.tag_neutron_resources(ports) for index, port in enumerate(ports): subports_info[index]['port_id'] = port['id'] @@ -139,6 +144,11 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): if security_groups: port_req_body['security_groups'] = security_groups + if self._tag_on_creation: + tags = CONF.neutron_defaults.resource_tags + if tags: + port_req_body['tags'] = tags + return port_req_body def _create_subports_info(self, pod, project_id, subnets, @@ -149,7 +159,7 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): in_use_vlan_ids = self._get_in_use_vlan_ids_set(trunk_id) port_rq = self._get_port_request(pod, project_id, subnets, security_groups, unbound) - for i in range(num_ports): + for _ in range(num_ports): try: vlan_id = seg_driver.allocate_segmentation_id(in_use_vlan_ids) except kl_exc.SegmentationIdAllocationFailure: @@ -194,7 +204,7 @@ class NestedVlanPodVIFDriver(nested_vif.NestedPodVIFDriver): raise subport = [{'segmentation_id': vlan_id, 'port_id': subport, - 'segmentation_type': 'vlan'}] + 'segmentation_type': 'vlan'}] try: os_net.add_trunk_subports(trunk_id, subport) except os_exc.ConflictException: diff --git a/kuryr_kubernetes/controller/drivers/neutron_vif.py b/kuryr_kubernetes/controller/drivers/neutron_vif.py index ca94d57da..eef5d7a91 100644 --- a/kuryr_kubernetes/controller/drivers/neutron_vif.py +++ b/kuryr_kubernetes/controller/drivers/neutron_vif.py @@ -15,6 +15,7 @@ from kuryr.lib import constants as kl_const from openstack import exceptions as os_exc +from oslo_config import cfg from oslo_log import log as logging from kuryr_kubernetes import clients @@ -28,10 +29,23 @@ from kuryr_kubernetes import os_vif_util as ovu LOG = logging.getLogger(__name__) +CONF = cfg.CONF + class NeutronPodVIFDriver(base.PodVIFDriver): """Manages normal Neutron ports to provide VIFs for Kubernetes Pods.""" + def __init__(self): + super(NeutronPodVIFDriver, self).__init__() + + self._tag_on_creation = utils.check_tag_on_creation() + if self._tag_on_creation: + LOG.info('Neutron supports tagging during bulk port creation.') + else: + LOG.warning('Neutron does not support tagging during bulk ' + 'port creation. Kuryr will tag resources after ' + 'port creation.') + def request_vif(self, pod, project_id, subnets, security_groups): os_net = clients.get_network_client() @@ -39,7 +53,8 @@ class NeutronPodVIFDriver(base.PodVIFDriver): port = os_net.create_port(**rq) self._check_port_binding([port]) - utils.tag_neutron_resources([port]) + if not self._tag_on_creation: + utils.tag_neutron_resources([port]) return ovu.neutron_to_osvif_vif(port.binding_vif_type, port, subnets) def request_vifs(self, pod, project_id, subnets, security_groups, @@ -67,7 +82,8 @@ class NeutronPodVIFDriver(base.PodVIFDriver): vif_plugin = port_info.binding_vif_type self._check_port_binding(ports) - utils.tag_neutron_resources(ports) + if not self._tag_on_creation: + utils.tag_neutron_resources(ports) vifs = [] for port in ports: vif = ovu.neutron_to_osvif_vif(vif_plugin, port, subnets) @@ -125,6 +141,11 @@ class NeutronPodVIFDriver(base.PodVIFDriver): if security_groups: port_req_body['security_groups'] = security_groups + if self._tag_on_creation: + tags = CONF.neutron_defaults.resource_tags + if tags: + port_req_body['tags'] = tags + return port_req_body def _check_port_binding(self, ports): diff --git a/kuryr_kubernetes/controller/drivers/sriov.py b/kuryr_kubernetes/controller/drivers/sriov.py index d3411417f..b16eeef0b 100644 --- a/kuryr_kubernetes/controller/drivers/sriov.py +++ b/kuryr_kubernetes/controller/drivers/sriov.py @@ -13,6 +13,7 @@ # under the License. from kuryr.lib import constants as kl_const +from oslo_config import cfg from oslo_log import log as logging from kuryr_kubernetes import clients @@ -23,6 +24,7 @@ from kuryr_kubernetes.controller.drivers import utils as c_utils from kuryr_kubernetes import os_vif_util as ovu LOG = logging.getLogger(__name__) +CONF = cfg.CONF def sriov_make_resource(prefix, res_name): @@ -57,7 +59,8 @@ class SriovVIFDriver(neutron_vif.NeutronPodVIFDriver): port = os_net.create_port(**rq) self._check_port_binding([port]) - c_utils.tag_neutron_resources([port]) + if not self._tag_on_creation: + c_utils.tag_neutron_resources([port]) vif = ovu.neutron_to_osvif_vif(vif_plugin, port, subnets) vif.physnet = physnet vif.pod_name = pod_name @@ -178,4 +181,9 @@ class SriovVIFDriver(neutron_vif.NeutronPodVIFDriver): if security_groups: port_req_body['security_groups'] = security_groups + if self._tag_on_creation: + tags = CONF.neutron_defaults.resource_tags + if tags: + port_req_body['tags'] = tags + return port_req_body diff --git a/kuryr_kubernetes/controller/drivers/utils.py b/kuryr_kubernetes/controller/drivers/utils.py index dc66ecebc..469ffb320 100644 --- a/kuryr_kubernetes/controller/drivers/utils.py +++ b/kuryr_kubernetes/controller/drivers/utils.py @@ -208,6 +208,18 @@ def create_security_group_rule(body): raise +def check_tag_on_creation(): + """Checks if Neutron supports tagging during bulk port creation. + + :param os_net: Network proxy object from Openstacksdk. + :return: Boolean + """ + os_net = clients.get_network_client() + extension = os_net.find_extension( + name_or_id='tag-ports-during-bulk-creation') + return bool(extension) + + def delete_security_group_rule(security_group_rule_id): os_net = clients.get_network_client() try: diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_macvlan_vif.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_macvlan_vif.py index 04e578d1b..b7e3b22eb 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_macvlan_vif.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_macvlan_vif.py @@ -32,6 +32,7 @@ class TestNestedMacvlanPodVIFDriver(test_base.TestCase): 'kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif_nested_macvlan') def test_request_vif(self, m_to_vif): cls = nested_macvlan_vif.NestedMacvlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -69,6 +70,7 @@ class TestNestedMacvlanPodVIFDriver(test_base.TestCase): 'kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif_nested_macvlan') def test_request_vif_port_create_failed(self, m_to_vif): cls = nested_macvlan_vif.NestedMacvlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -93,6 +95,7 @@ class TestNestedMacvlanPodVIFDriver(test_base.TestCase): 'kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif_nested_macvlan') def test_request_vif_parent_not_found(self, m_to_vif): cls = nested_macvlan_vif.NestedMacvlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_vlan_vif.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_vlan_vif.py index 2782ebb83..e6b6a7fc8 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_vlan_vif.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_nested_vlan_vif.py @@ -31,6 +31,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): 'kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif_nested_vlan') def test_request_vif(self, m_to_vif): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -75,6 +76,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): 'kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif_nested_vlan') def test_request_vifs(self, m_to_vif): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -124,6 +126,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): def test_request_vifs_no_vlans(self): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = False m_driver = mock.Mock(spec=cls) self.useFixture(k_fix.MockNetworkClient()).client @@ -155,6 +158,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): def test_request_vifs_bulk_creation_exception(self): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -195,6 +199,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): def test_request_vifs_trunk_subports_conflict(self): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -239,6 +244,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): def test_request_vifs_trunk_subports_exception(self): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = False m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -326,6 +332,7 @@ class TestNestedVlanPodVIFDriver(test_base.TestCase): m_get_network_id, m_get_port_name, unbound=False): cls = nested_vlan_vif.NestedVlanPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) pod = mock.sentinel.pod diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_neutron_vif.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_neutron_vif.py index 33bb35813..13c3aa8df 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_neutron_vif.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_neutron_vif.py @@ -33,6 +33,7 @@ class NeutronPodVIFDriver(test_base.TestCase): @mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif') def test_request_vif(self, m_to_vif): cls = neutron_vif.NeutronPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -61,6 +62,7 @@ class NeutronPodVIFDriver(test_base.TestCase): @mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif') def test_request_vifs(self, m_to_vif): cls = neutron_vif.NeutronPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -94,6 +96,7 @@ class NeutronPodVIFDriver(test_base.TestCase): @mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif') def test_request_vifs_unbound(self, m_to_vif): cls = neutron_vif.NeutronPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -131,6 +134,7 @@ class NeutronPodVIFDriver(test_base.TestCase): @mock.patch('kuryr_kubernetes.os_vif_util.neutron_to_osvif_vif') def test_request_vifs_exception(self, m_to_vif): cls = neutron_vif.NeutronPodVIFDriver + cls._tag_on_creation = False m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client @@ -227,6 +231,7 @@ class NeutronPodVIFDriver(test_base.TestCase): m_get_device_id, m_get_port_name, m_get_host_id, m_get_network_id, unbound=False): cls = neutron_vif.NeutronPodVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) pod = mock.sentinel.pod @@ -259,6 +264,10 @@ class NeutronPodVIFDriver(test_base.TestCase): if security_groups: expected['security_groups'] = security_groups + tags = oslo_cfg.CONF.neutron_defaults.resource_tags + if cls._tag_on_creation and tags: + expected['tags'] = tags + if unbound: expected['name'] = constants.KURYR_PORT_NAME else: diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_sriov.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_sriov.py index abcf05386..8a26b0e0d 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_sriov.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_sriov.py @@ -81,6 +81,7 @@ class TestSriovVIFDriver(test_base.TestCase): @mock.patch.object(ovu, 'neutron_to_osvif_vif') def test_request_vif(self, m_to_vif, m_to_fips): cls = drvs.SriovVIFDriver + cls._tag_on_creation = True m_driver = mock.Mock(spec=cls) os_net = self.useFixture(k_fix.MockNetworkClient()).client diff --git a/kuryr_kubernetes/tests/unit/controller/handlers/test_kuryrport.py b/kuryr_kubernetes/tests/unit/controller/handlers/test_kuryrport.py index 2031a0b34..c01c40c08 100644 --- a/kuryr_kubernetes/tests/unit/controller/handlers/test_kuryrport.py +++ b/kuryr_kubernetes/tests/unit/controller/handlers/test_kuryrport.py @@ -24,6 +24,7 @@ from kuryr_kubernetes.controller.drivers import multi_vif from kuryr_kubernetes.controller.handlers import kuryrport from kuryr_kubernetes import exceptions as k_exc from kuryr_kubernetes.tests import base as test_base +from kuryr_kubernetes.tests.unit import kuryr_fixtures as k_fix CONF = cfg.CONF @@ -87,6 +88,7 @@ class TestKuryrPortHandler(test_base.TestCase): self._pod_uri = (f"{constants.K8S_API_NAMESPACES}" f"/{self._kp['metadata']['namespace']}/pods/" f"{self._kp['metadata']['name']}") + self.useFixture(k_fix.MockNetworkClient()) self._driver = multi_vif.NoopMultiVIFDriver() @mock.patch('kuryr_kubernetes.controller.handlers.kuryrport.'