Make FloatingIP depend on all RouterInterfaces again

It used to be that a FloatingIP would depend on all RouterInterfaces that
it couldn't determine were on a different subnet to the port the FloatingIP
was attaching to (by virtue of the Subnet value being None in both cases,
and therefore matching). That changed in
c9f32bfef0 to depending only on
RouterInterfaces that it *could* determine *were* in the same subnet. This
resulted in no dependency being added at create time when the Subnet was a
resource in the local stack (as opposed to being passed in e.g. as a
parameter).

That caused problems with some Neutron plugins, but worked with others
where the dependencies were required only at delete time (at this point the
in-template Subnets had IDs and therefore the dependencies were fully
determined). However, with convergence phase 1 enabled, the dependencies
calculated at create time are used throughout the lifecycle of the stack,
thus causing non-deterministic ordering problems at delete time.

This patch restores the behaviour where if the Subnet for a RouterInterface
cannot be determined, the FloatingIP will depend on it. It also corrects a
bug where we only checked the first Subnet if multiple Networks/Subnets
were listed for the port.

Change-Id: I185e30b2247c5b423d319506f60864c3027fc4fe
Closes-Bug: #1626619
This commit is contained in:
Zane Bitter 2016-11-04 16:06:43 -04:00
parent 020cd3d722
commit d5ef455f66
1 changed files with 16 additions and 8 deletions

View File

@ -199,8 +199,18 @@ class FloatingIP(neutron.NeutronResource):
def port_on_subnet(resource, subnet):
if not resource.has_interface('OS::Neutron::Port'):
return False
fixed_ips = resource.properties.get(port.Port.FIXED_IPS)
if not fixed_ips:
# During create we have only unresolved value for
# functions, so can not use None value for building
# correct dependencies. Depend on all RouterInterfaces
# when the port has no fixed IP specified, since we
# can't safely assume that any are in different
# networks.
if subnet is None:
return True
p_net = (resource.properties.get(port.Port.NETWORK) or
resource.properties.get(port.Port.NETWORK_ID))
if p_net:
@ -214,19 +224,17 @@ class FloatingIP(neutron.NeutronResource):
port_subnet = (
fixed_ip.get(port.Port.FIXED_IP_SUBNET)
or fixed_ip.get(port.Port.FIXED_IP_SUBNET_ID))
return subnet == port_subnet
if subnet == port_subnet:
return True
return False
interface_subnet = (
resource.properties.get(router.RouterInterface.SUBNET) or
resource.properties.get(router.RouterInterface.SUBNET_ID))
# during create we have only unresolved value for functions, so
# can not use None value for building correct dependencies
if interface_subnet:
for d in deps.graph()[self]:
if port_on_subnet(d, interface_subnet):
deps += (self, resource)
break
for d in deps.graph()[self]:
if port_on_subnet(d, interface_subnet):
deps += (self, resource)
break
# depend on Router with EXTERNAL_GATEWAY_NETWORK property
# this template with the same network_id as this
# floating_network_id