From 63735680c3011429dd3ab920be8be684d5e38bc5 Mon Sep 17 00:00:00 2001 From: Hongbin Lu Date: Sun, 26 Jan 2020 00:01:59 +0000 Subject: [PATCH] Move port deletion code to zun/network/neutron.py This allows the neutron port cleanup logic to be reused by other runtimes. Change-Id: I213fa67057a5fceaa9a150ab7c68aedd5f2eb4b0 --- zun/network/kuryr_network.py | 48 +------------------- zun/network/neutron.py | 48 ++++++++++++++++++++ zun/tests/unit/network/test_kuryr_network.py | 8 ++++ 3 files changed, 57 insertions(+), 47 deletions(-) diff --git a/zun/network/kuryr_network.py b/zun/network/kuryr_network.py index 4e49819ce..73d6ba944 100644 --- a/zun/network/kuryr_network.py +++ b/zun/network/kuryr_network.py @@ -285,53 +285,7 @@ class KuryrNetwork(network.Network): self.docker.disconnect_container_from_network(container_id, network_name) finally: - for port_id in all_ports: - try: - if port_id in neutron_ports: - self.neutron_api.delete_port(port_id) - else: - self._unbind_port(port_id) - except exceptions.PortNotFoundClient: - LOG.warning('Maybe your libnetwork distribution do not ' - 'have patch https://review.openstack.org/#/c/' - '441024/ or neutron tag extension does not ' - 'supported or not enabled.') - - def _unbind_port(self, port_id): - port_req_body = {'port': {'device_id': '', 'device_owner': ''}} - port_req_body['port'][consts.BINDING_HOST_ID] = None - try: - port = self.neutron_api.get_neutron_port(port_id) - except exception.PortNotFound: - LOG.debug('Unable to show port %s as it no longer ' - 'exists.', port_id) - return - except Exception: - # NOTE: In case we can't retrieve the binding:profile assume - # that they are empty - LOG.exception("Unable to get binding:profile for port '%s'", - port_id) - port_profile = {} - else: - port_profile = port.get(consts.BINDING_PROFILE, {}) - # NOTE: We're doing this to remove the binding information - # for the physical device but don't want to overwrite the other - # information in the binding profile. - for profile_key in ('pci_vendor_info', 'pci_slot'): - if profile_key in port_profile: - del port_profile[profile_key] - port_req_body['port'][consts.BINDING_PROFILE] = port_profile - - try: - # Requires admin creds to set port bindings - self.neutron_api.update_port(port_id, port_req_body, - admin=True) - except exception.PortNotFound: - LOG.debug('Unable to unbind port %s as it no longer ' - 'exists.', port_id) - except Exception: - LOG.exception("Unable to clear device ID for port '%s'", - port_id) + self.neutron_api.delete_or_unbind_ports(all_ports, neutron_ports) def add_security_groups_to_ports(self, container, security_group_ids): port_ids = set() diff --git a/zun/network/neutron.py b/zun/network/neutron.py index 30641ba42..b8356e3b0 100644 --- a/zun/network/neutron.py +++ b/zun/network/neutron.py @@ -138,6 +138,54 @@ class NeutronAPI(object): return addresses, neutron_port + def delete_or_unbind_ports(self, ports, ports_to_delete): + for port_id in ports: + try: + if port_id in ports_to_delete: + self.delete_port(port_id) + else: + self._unbind_port(port_id) + except n_exceptions.PortNotFoundClient: + LOG.warning('Maybe your libnetwork distribution do not ' + 'have patch https://review.openstack.org/#/c/' + '441024/ or neutron tag extension does not ' + 'supported or not enabled.') + + def _unbind_port(self, port_id): + port_req_body = {'port': {'device_id': '', 'device_owner': ''}} + port_req_body['port'][consts.BINDING_HOST_ID] = None + try: + port = self.get_neutron_port(port_id) + except exception.PortNotFound: + LOG.debug('Unable to show port %s as it no longer ' + 'exists.', port_id) + return + except Exception: + # NOTE: In case we can't retrieve the binding:profile assume + # that they are empty + LOG.exception("Unable to get binding:profile for port '%s'", + port_id) + port_profile = {} + else: + port_profile = port.get(consts.BINDING_PROFILE, {}) + # NOTE: We're doing this to remove the binding information + # for the physical device but don't want to overwrite the other + # information in the binding profile. + for profile_key in ('pci_vendor_info', 'pci_slot'): + if profile_key in port_profile: + del port_profile[profile_key] + port_req_body['port'][consts.BINDING_PROFILE] = port_profile + + try: + # Requires admin creds to set port bindings + self.update_port(port_id, port_req_body, admin=True) + except exception.PortNotFound: + LOG.debug('Unable to unbind port %s as it no longer ' + 'exists.', port_id) + except Exception: + LOG.exception("Unable to clear device ID for port '%s'", + port_id) + def _refresh_neutron_extensions_cache(self): """Refresh the neutron extensions cache when necessary.""" if (not self.last_neutron_extension_sync or diff --git a/zun/tests/unit/network/test_kuryr_network.py b/zun/tests/unit/network/test_kuryr_network.py index 982f60a9f..ef29f3731 100644 --- a/zun/tests/unit/network/test_kuryr_network.py +++ b/zun/tests/unit/network/test_kuryr_network.py @@ -116,6 +116,14 @@ class FakeNeutronClient(object): return addresses, neutron_port + def delete_or_unbind_ports(self, ports, ports_to_delete): + for port_id in ports: + if port_id in ports_to_delete: + self.delete_port(port_id) + else: + port_req_body = {'port': {'device_id': ''}} + self.update_port(port_id, port_req_body) + def delete_port(self, port_id): for port in self.ports: if port['id'] == port_id: