Merge "Block flip update if fixed ip conflicts with gw."

This commit is contained in:
Jenkins 2016-06-30 18:54:47 +00:00 committed by Gerrit Code Review
commit 15671d45ef
4 changed files with 80 additions and 4 deletions

View File

@ -204,6 +204,11 @@ class PortAlreadyContainsFloatingIp(n_exc.Conflict):
message = _("Port %(port_id)s already has an associated floating IP.")
class FixedIpAllocatedToGatewayIp(n_exc.Conflict):
message = _("Gateway IP of Floating IP subnet conflicts with Fixed IP "
"allocated to port %(port_id)s of network %(network_id)s.")
class FixedIpDoesNotExistsForPort(n_exc.BadRequest):
message = _("Fixed IP %(fixed_ip)s does not exist on Port %(port_id)s")

View File

@ -220,6 +220,27 @@ def _update_flip(context, flip_id, ip_type, requested_ports):
not curr_port_ids and not req_port_ids):
raise q_exc.FloatingIpUpdateNoPortIdSupplied()
# Validate that GW IP is not in use on the NW.
flip_subnet = v._make_subnet_dict(flip.subnet)
for added_port_id in added_port_ids:
port = _get_port(context, added_port_id)
nw = port.network
nw_ports = v._make_ports_list(nw.ports)
fixed_ips = [ip.get('ip_address') for p in nw_ports
for ip in p.get('fixed_ips')]
gw_ip = flip_subnet.get('gateway_ip')
if gw_ip in fixed_ips:
port_with_gateway_ip = None
for port in nw_ports:
for ip in port.get('fixed_ips'):
if gw_ip in ip.get('ip_address'):
port_with_gateway_ip = port
break
port_id = port_with_gateway_ip.get('id')
network_id = port_with_gateway_ip.get('network_id')
raise q_exc.FixedIpAllocatedToGatewayIp(port_id=port_id,
network_id=network_id)
port_fixed_ips = {}
# Keep the ports and fixed ips that have not changed

View File

@ -104,7 +104,7 @@ def _make_subnet_dict(subnet, fields=None):
if (CONF.QUARK.show_allocation_pools and not
STRATEGY.is_provider_subnet(subnet_id)):
res["allocation_pools"] = subnet.allocation_pools
res["allocation_pools"] = subnet.get('allocation_pools', [])
else:
res["allocation_pools"] = []

View File

@ -485,7 +485,8 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
self.addCleanup(reset_refresh, self.context)
@contextlib.contextmanager
def _stubs(self, flip=None, curr_port=None, new_port=None, ips=None):
def _stubs(self, flip=None, curr_port=None, new_port=None, ips=None,
subnet=None, network=None):
curr_port_model = None
if curr_port:
curr_port_model = models.Port()
@ -508,10 +509,20 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
ip_model.fixed_ip = fixed_ip
new_port_model.ip_addresses.append(ip_model)
subnet_model = None
if subnet:
subnet_model = models.Subnet()
subnet_model.update(subnet)
else:
subnet_model = models.Subnet(id=1, network_id=1, name=1,
tenant_id=1, ip_version=4,
dns_nameservers=[],
cidr="192.168.0.0/24")
flip_model = None
if flip:
flip_model = models.IPAddress()
flip_model.update(flip)
flip_model.subnet = subnet_model
if curr_port_model:
flip_model.ports = [curr_port_model]
fixed_ip = flip.get("fixed_ip_address")
@ -523,6 +534,11 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
address_type="fixed"))
flip_model.fixed_ip = fixed_ip_model
net_model = models.Network()
if network:
net_model.update(network)
net_model.ports = [new_port_model]
def _find_port(context, id, **kwargs):
return (curr_port_model if (curr_port_model and
id == curr_port_model.id)
@ -551,6 +567,8 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
with contextlib.nested(
mock.patch("quark.db.api.floating_ip_find"),
mock.patch("quark.db.api.network_find"),
mock.patch("quark.db.api.subnet_find"),
mock.patch("quark.db.api.port_find"),
mock.patch("quark.drivers.unicorn_driver.UnicornDriver"
".register_floating_ip"),
@ -563,9 +581,12 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
mock.patch("quark.db.api.floating_ip_associate_fixed_ip"),
mock.patch("quark.db.api.floating_ip_disassociate_fixed_ip"),
mock.patch("quark.billing.notify")
) as (flip_find, port_find, reg_flip, update_flip, rem_flip,
port_assoc, port_dessoc, flip_assoc, flip_dessoc, notify):
) as (flip_find, net_find, subnet_find, port_find, reg_flip,
update_flip, rem_flip, port_assoc, port_dessoc, flip_assoc,
flip_dessoc, notify):
flip_find.return_value = flip_model
net_find.return_value = net_model
subnet_find.return_value = subnet_model
port_find.side_effect = _find_port
port_assoc.side_effect = _port_assoc
port_dessoc.side_effect = _port_dessoc
@ -576,6 +597,35 @@ class TestUpdateFloatingIPs(test_quark_plugin.TestQuarkPlugin):
# arguments it was called.
yield notify
def test_update_with_conflicted_fixed_ip_and_gateway(self):
floating_ip_addr = netaddr.IPAddress("10.0.0.1")
flip = dict(id=1, address=int(floating_ip_addr), version=4,
address_readable=str(floating_ip_addr), subnet_id=1,
network_id=2, used_by_tenant_id=1)
network = dict(id="00000000-0000-0000-0000-000000000000",
ipam_strategy="ANY")
subnet = dict(id=1, network_id=1, name=1,
tenant_id=1, ip_version=4,
routes=[models.Route(cidr='0.0.0.0',
gateway='192.168.0.1')],
cidr="192.168.0.0/24",
dns_nameservers=[],
enable_dhcp=None)
fixed_ip_addr = netaddr.IPAddress("192.168.0.1")
fixed_ips = [dict(address_type="fixed", address=int(fixed_ip_addr),
version=4, address_readable=str(fixed_ip_addr),
allocated_at=datetime.datetime.now())]
new_port = dict(id="abcdefgh-1111-2222-3333-1234567890ab")
with self._stubs(flip=flip, new_port=new_port,
ips=fixed_ips, subnet=subnet, network=network):
with self.assertRaises(
q_ex.FixedIpAllocatedToGatewayIp):
content = dict(port_id=new_port["id"])
self.plugin.update_floatingip(self.context, flip["id"],
dict(floatingip=content))
def test_update_with_new_port_and_no_previous_port(self):
new_port = dict(id="2")