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 95943c6be27..65ea3218337 100644 --- a/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/openvswitch/agent/ovs_neutron_agent.py @@ -1683,6 +1683,11 @@ class OVSNeutronAgent(l2population_rpc.L2populationRpcCallBackTunnelMixin, if name not in current: continue current_ofport = current[name] + # NOTE(amorin) Discarding port that disappeared from ovs + # This will avoid moving that port to skipped_devices + # and forget about deleting it. See #lp-1992109 + if current_ofport == ovs_lib.INVALID_OFPORT: + continue if ofport != current_ofport: port_moves.append(name) return port_moves 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 06efeabcf42..2a7532b618c 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 @@ -2512,6 +2512,14 @@ class TestOvsNeutronAgent(object): self.assertEqual(expected, self.agent._get_ofport_moves(current, previous)) + def test__get_ofport_moves_invalid(self): + previous = {'port1': 1, 'port2': 2} + current = {'port1': -1, 'port2': 2} + # we expect it to tell nothing + expected = [] + self.assertEqual(expected, + self.agent._get_ofport_moves(current, previous)) + def test_update_stale_ofport_rules_clears_old(self): self.agent.prevent_arp_spoofing = True self.agent.vifname_to_ofport_map = {'port1': 1, 'port2': 2}