Skip attaching FloatingIP if it is already attached

There are some flows in the cloud layer (reuse, but not found), which
try to attach a freshly allocated (and attached) FIP. There is at least
one cloud in the crowd, which explicitely forbids FIP attachment when it
is already attached, what results in SDK and Ansible failure with
auto_ip=True

The test test_add_ip_refresh_timeout is being removed, since normally we
should never end up this way (with reuse=False we wait for the FIP to be
assigned during creation and we leave _add_auto_ip on a short-cut)

Change-Id: If9a217981237d6f851ee470717da01fddd1b5ff1
This commit is contained in:
Artem Goncharov 2019-04-15 14:34:00 +02:00
parent 1d410a49c8
commit f9483e5d95
2 changed files with 15 additions and 54 deletions

View File

@ -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']:

View File

@ -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):