From 1b25e30800c869dacca58afa6b8bf92f4cf9d377 Mon Sep 17 00:00:00 2001 From: rossella Date: Wed, 26 Aug 2015 16:06:25 +0000 Subject: [PATCH] _bind_devices query only existing ports If a port is deleted right before _bind_devices is called, get_ports_attributes will throw an exception since the row corresponding to the port doesn't exist in the OVS DB. Avoid that setting if_exists to True. The port will be processed as deleted by the agent in the following iteration. Change-Id: Ia6590d76f8683e6cba562cde3c39b051549f6c04 Closes-bug: #1489014 --- .../drivers/openvswitch/agent/ovs_neutron_agent.py | 6 +++++- .../openvswitch/agent/test_ovs_neutron_agent.py | 14 ++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py index ecb92dc92..b6ba20bdb 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -793,7 +793,7 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, devices_down = [] port_names = [p['vif_port'].port_name for p in need_binding_ports] port_info = self.int_br.get_ports_attributes( - "Port", columns=["name", "tag"], ports=port_names) + "Port", columns=["name", "tag"], ports=port_names, if_exists=True) tags_by_name = {x['name']: x['tag'] for x in port_info} for port_detail in need_binding_ports: lvm = self.local_vlan_map.get(port_detail['network_id']) @@ -805,6 +805,10 @@ class OVSNeutronAgent(sg_rpc.SecurityGroupAgentRpcCallbackMixin, device = port_detail['device'] # Do not bind a port if it's already bound cur_tag = tags_by_name.get(port.port_name) + if cur_tag is None: + LOG.info(_LI("Port %s was deleted concurrently, skipping it"), + port.port_name) + continue if cur_tag != lvm.vlan: self.int_br.delete_flows(in_port=port.ofport) if self.prevent_arp_spoofing: diff --git a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py index 401deb756..df6c8780d 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/openvswitch/agent/test_ovs_neutron_agent.py @@ -368,11 +368,17 @@ class TestOvsNeutronAgent(object): devices_up = ['tap1'] devices_down = ['tap2'] self.agent.local_vlan_map["net1"] = mock.Mock() + ovs_db_list = [{'name': 'tap1', 'tag': []}, + {'name': 'tap2', 'tag': []}] + vif_port1 = mock.Mock() + vif_port1.port_name = 'tap1' + vif_port2 = mock.Mock() + vif_port2.port_name = 'tap2' port_details = [ - {'network_id': 'net1', 'vif_port': mock.Mock(), + {'network_id': 'net1', 'vif_port': vif_port1, 'device': devices_up[0], 'admin_state_up': True}, - {'network_id': 'net1', 'vif_port': mock.Mock(), + {'network_id': 'net1', 'vif_port': vif_port2, 'device': devices_down[0], 'admin_state_up': False}] with mock.patch.object( @@ -383,7 +389,7 @@ class TestOvsNeutronAgent(object): 'failed_devices_down': []}) as update_devices, \ mock.patch.object(self.agent, 'int_br') as int_br: - int_br.db_list.return_value = [] + int_br.get_ports_attributes.return_value = ovs_db_list self.agent._bind_devices(port_details) update_devices.assert_called_once_with(mock.ANY, devices_up, devices_down, @@ -413,7 +419,7 @@ class TestOvsNeutronAgent(object): mock.patch.object( self.agent, 'setup_arp_spoofing_protection') as setup_arp: - int_br.db_list.return_value = ovs_db_list + int_br.get_ports_attributes.return_value = ovs_db_list self.agent._bind_devices(need_binding_ports) self.assertEqual(enable_prevent_arp_spoofing, setup_arp.called) -- 2.45.2