diff --git a/kuryr_kubernetes/controller/drivers/public_ip.py b/kuryr_kubernetes/controller/drivers/public_ip.py index e92541598..8b26a2848 100644 --- a/kuryr_kubernetes/controller/drivers/public_ip.py +++ b/kuryr_kubernetes/controller/drivers/public_ip.py @@ -138,10 +138,20 @@ class FipPubIpDriver(BasePubIpDriver): try: response = neutron.update_floatingip( res_id, {'floatingip': {'port_id': vip_port_id, }}) - except n_exc.NeutronClientException as ex: + except n_exc.Conflict: + LOG.warning("Conflict when assigning floating IP with id %s. " + "Checking if it's already assigned correctly.", res_id) + fip = neutron.get_floatingip(res_id) + used_port_id = fip['port_id'] + if used_port_id != vip_port_id: + LOG.exception("Floating IP already used by port %s.", + used_port_id) + raise + + except n_exc.NeutronClientException: LOG.error("Failed to update_floatingip ,floating_ip_id=%s," "response=%s!", res_id, response) - raise ex + raise def associate(self, res_id, vip_port_id): self._update(res_id, vip_port_id) diff --git a/kuryr_kubernetes/tests/unit/controller/drivers/test_public_ip.py b/kuryr_kubernetes/tests/unit/controller/drivers/test_public_ip.py index d638aa8bc..44f1fddda 100644 --- a/kuryr_kubernetes/tests/unit/controller/drivers/test_public_ip.py +++ b/kuryr_kubernetes/tests/unit/controller/drivers/test_public_ip.py @@ -121,6 +121,28 @@ class TestFipPubIpDriver(test_base.TestCase): self.assertRaises(n_exc.NeutronClientException, self.driver.associate, res_id, vip_port_id) + def test_associate_conflict_correct(self): + driver = d_public_ip.FipPubIpDriver() + res_id = mock.sentinel.res_id + vip_port_id = mock.sentinel.vip_port_id + + neutron = self.useFixture(k_fix.MockNeutronClient()).client + neutron.update_floatingip.side_effect = n_exc.Conflict + neutron.get_floatingip.return_value = {'id': res_id, + 'port_id': vip_port_id} + self.assertIsNone(driver.associate(res_id, vip_port_id)) + + def test_associate_conflict_incorrect(self): + driver = d_public_ip.FipPubIpDriver() + res_id = mock.sentinel.res_id + vip_port_id = mock.sentinel.vip_port_id + + neutron = self.useFixture(k_fix.MockNeutronClient()).client + neutron.update_floatingip.side_effect = n_exc.Conflict + neutron.get_floatingip.return_value = {'id': res_id, 'port_id': 'foo'} + self.assertRaises(n_exc.Conflict, driver.associate, res_id, + vip_port_id) + def test_associate_succeeded(self): res_id = mock.sentinel.res_id vip_port_id = mock.sentinel.vip_port_id