diff --git a/openstack/cloud/_floating_ip.py b/openstack/cloud/_floating_ip.py index 5235fdffe..98068ad9b 100644 --- a/openstack/cloud/_floating_ip.py +++ b/openstack/cloud/_floating_ip.py @@ -691,6 +691,15 @@ class FloatingIPCloudMixin(_normalize.Normalizer): # Short circuit if we're asking to attach an IP that's already # attached ext_ip = meta.get_server_ip(server, ext_tag='floating', public=True) + if not ext_ip and floating_ip['port_id']: + # When we came here from reuse_fip and created FIP it might be + # already attached, but the server info might be also + # old to check whether it belongs to us now, thus refresh + # the server data and try again. There are some clouds, which + # explicitely forbids FIP assign call if it is already assigned. + server = self.get_server_by_id(server['id']) + ext_ip = meta.get_server_ip(server, ext_tag='floating', + public=True) if ext_ip == floating_ip['floating_ip_address']: return server @@ -719,7 +728,7 @@ class FloatingIPCloudMixin(_normalize.Normalizer): timeout, "Timeout waiting for the floating IP to be attached.", wait=self._SERVER_AGE): - server = self.get_server(server_id) + server = self.get_server_by_id(server_id) ext_ip = meta.get_server_ip( server, ext_tag='floating', public=True) if ext_ip == floating_ip['floating_ip_address']: diff --git a/openstack/tests/unit/cloud/test_floating_ip_neutron.py b/openstack/tests/unit/cloud/test_floating_ip_neutron.py index 94c06bdc0..d2f72f097 100644 --- a/openstack/tests/unit/cloud/test_floating_ip_neutron.py +++ b/openstack/tests/unit/cloud/test_floating_ip_neutron.py @@ -768,7 +768,8 @@ class TestFloatingIP(base.TestCase): self.assert_calls() def test_attach_ip_to_server(self): - fip = self.mock_floating_ip_list_rep['floatingips'][0] + fip = self.mock_floating_ip_list_rep['floatingips'][0].copy() + fip.update({'status': 'DOWN', 'port_id': None, 'router_id': None}) device_id = self.fake_server['id'] self.register_uris([ @@ -782,7 +783,8 @@ class TestFloatingIP(base.TestCase): 'network', 'public', append=['v2.0', 'floatingips/{0}.json'.format( fip['id'])]), - json={'floatingip': fip}, + json={'floatingip': + self.mock_floating_ip_list_rep['floatingips'][0]}, validate=dict( json={'floatingip': { 'port_id': self.mock_search_ports_rep[0]['id'], @@ -792,57 +794,7 @@ class TestFloatingIP(base.TestCase): self.cloud._attach_ip_to_server( server=self.fake_server, - floating_ip=self.floating_ip) - self.assert_calls() - - def test_add_ip_refresh_timeout(self): - device_id = self.fake_server['id'] - - self.register_uris([ - dict(method='GET', - uri=self.get_mock_url( - 'network', 'public', - append=['v2.0', 'networks.json']), - json={'networks': [self.mock_get_network_rep]}), - dict(method='GET', - uri='https://network.example.com/v2.0/subnets.json', - json={'subnets': []}), - dict(method='GET', - uri=self.get_mock_url( - 'network', 'public', append=['v2.0', 'ports.json'], - qs_elements=["device_id={0}".format(device_id)]), - json={'ports': self.mock_search_ports_rep}), - dict(method='POST', - uri='https://network.example.com/v2.0/floatingips.json', - json={'floatingip': self.floating_ip}, - validate=dict( - json={'floatingip': { - 'floating_network_id': 'my-network-id', - 'fixed_ip_address': self.mock_search_ports_rep[0][ - 'fixed_ips'][0]['ip_address'], - 'port_id': self.mock_search_ports_rep[0]['id']}})), - dict(method='GET', - uri=self.get_mock_url( - 'network', 'public', append=['v2.0', 'floatingips.json']), - json={'floatingips': [self.floating_ip]}), - dict(method='DELETE', - uri=self.get_mock_url( - 'network', 'public', - append=['v2.0', 'floatingips/{0}.json'.format( - self.floating_ip['id'])]), - json={}), - dict(method='GET', - uri=self.get_mock_url( - 'network', 'public', append=['v2.0', 'floatingips.json']), - json={'floatingips': []}), - ]) - - self.assertRaises( - exc.OpenStackCloudTimeout, - self.cloud._add_auto_ip, - server=self.fake_server, - wait=True, timeout=0.01, - reuse=False) + floating_ip=self.cloud._normalize_floating_ip(fip)) self.assert_calls() def test_detach_ip_from_server(self):