From d6a55c17360d1aa8ca91849199987ae71e8600ee Mon Sep 17 00:00:00 2001 From: Elena Ezhova Date: Wed, 24 Dec 2014 17:09:32 +0300 Subject: [PATCH] Remove port from ovsdb after its deletion When port is being deleted via API it is not removed from ovsdb and corresponding iptables chains remain even though the port does not exist. This patch adds a notification for the ovs neutron agent, upon which the port is deleted from ovsdb. Co-Authored-By: Akash Gangil Closes-Bug: #1333365 Change-Id: Iccda3bee98d561ef3a06d0317d3d68d6b1dfb76b --- neutron/plugins/ml2/plugin.py | 1 + neutron/plugins/ml2/rpc.py | 9 +++++++++ .../plugins/openvswitch/agent/ovs_neutron_agent.py | 8 ++++++++ neutron/tests/unit/ml2/test_rpcapi.py | 10 ++++++++++ .../unit/openvswitch/test_ovs_neutron_agent.py | 14 ++++++++++++++ 5 files changed, 42 insertions(+) diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index 411002dc7..bc719288c 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -1172,6 +1172,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # fact that an error occurred. LOG.error(_LE("mechanism_manager.delete_port_postcommit failed for" " port %s"), id) + self.notifier.port_delete(context, id) self.notify_security_groups_member_updated(context, port) def get_bound_port_context(self, plugin_context, port_id, host=None): diff --git a/neutron/plugins/ml2/rpc.py b/neutron/plugins/ml2/rpc.py index b08d06be1..6595c8291 100644 --- a/neutron/plugins/ml2/rpc.py +++ b/neutron/plugins/ml2/rpc.py @@ -198,6 +198,10 @@ class AgentNotifierApi(dvr_rpc.DVRAgentRpcApiMixin, self.topic_port_update = topics.get_topic_name(topic, topics.PORT, topics.UPDATE) + self.topic_port_delete = topics.get_topic_name(topic, + topics.PORT, + topics.DELETE) + target = oslo_messaging.Target(topic=topic, version='1.0') self.client = n_rpc.get_client(target) @@ -213,3 +217,8 @@ class AgentNotifierApi(dvr_rpc.DVRAgentRpcApiMixin, cctxt.cast(context, 'port_update', port=port, network_type=network_type, segmentation_id=segmentation_id, physical_network=physical_network) + + def port_delete(self, context, port_id): + cctxt = self.client.prepare(topic=self.topic_port_delete, + fanout=True) + cctxt.cast(context, 'port_delete', port_id=port_id) diff --git a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py index b1a3565bb..b3199421b 100644 --- a/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/openvswitch/agent/ovs_neutron_agent.py @@ -294,6 +294,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, self.endpoints = [self] # Define the listening consumers for the agent consumers = [[topics.PORT, topics.UPDATE], + [topics.PORT, topics.DELETE], [topics.NETWORK, topics.DELETE], [constants.TUNNEL, topics.UPDATE], [topics.SECURITY_GROUP, topics.UPDATE], @@ -331,6 +332,13 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, self.updated_ports.add(port['id']) LOG.debug("port_update message processed for port %s", port['id']) + def port_delete(self, context, **kwargs): + port_id = kwargs.get('port_id') + port = self.int_br.get_vif_port_by_id(port_id) + # If port exists, delete it + if port: + self.int_br.delete_port(port.port_name) + def tunnel_update(self, context, **kwargs): LOG.debug("tunnel_update received") if not self.enable_tunneling: diff --git a/neutron/tests/unit/ml2/test_rpcapi.py b/neutron/tests/unit/ml2/test_rpcapi.py index a3b4955f6..08978f66e 100644 --- a/neutron/tests/unit/ml2/test_rpcapi.py +++ b/neutron/tests/unit/ml2/test_rpcapi.py @@ -223,6 +223,16 @@ class RpcApiTestCase(base.BaseTestCase): segmentation_id='fake_segmentation_id', physical_network='fake_physical_network') + def test_port_delete(self): + rpcapi = plugin_rpc.AgentNotifierApi(topics.AGENT) + self._test_rpc_api( + rpcapi, + topics.get_topic_name(topics.AGENT, + topics.PORT, + topics.DELETE), + 'port_delete', rpc_method='cast', + fanout=True, port_id='fake_port') + def test_tunnel_update(self): rpcapi = plugin_rpc.AgentNotifierApi(topics.AGENT) self._test_rpc_api( diff --git a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py index 3e124fbf6..a7d90416f 100644 --- a/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/openvswitch/test_ovs_neutron_agent.py @@ -498,6 +498,20 @@ class TestOvsNeutronAgent(base.BaseTestCase): physical_network="physnet") self.assertEqual(set(['123']), self.agent.updated_ports) + def test_port_delete(self): + port_id = "123" + port_name = "foo" + with contextlib.nested( + mock.patch.object(self.agent.int_br, 'get_vif_port_by_id', + return_value=mock.MagicMock( + port_name=port_name)), + mock.patch.object(self.agent.int_br, "delete_port") + ) as (get_vif_func, del_port_func): + self.agent.port_delete("unused_context", + port_id=port_id) + self.assertTrue(get_vif_func.called) + del_port_func.assert_called_once_with(port_name) + def test_setup_physical_bridges(self): with contextlib.nested( mock.patch.object(ip_lib, "device_exists"), -- 2.45.2