Skip to content

Commit df5cb32

Browse files
committed
Remove any IPAM allocation if port bulk creation fails
During the port bulk creation, if an IPAM allocation fails (for example, if the IP address is outside of the subnet CIDR), the other IPAM allocations already created are deleted before raising the exception. Conflicts: neutron/tests/unit/plugins/ml2/test_plugin.py Closes-Bug: #2039550 Change-Id: I7fd6e38016d099c03f80874bfa1fb8bdaff8bd2c (cherry picked from commit 71a7abb) (cherry picked from commit a4c0367)
1 parent 56f4fe3 commit df5cb32

File tree

3 files changed

+44
-4
lines changed

3 files changed

+44
-4
lines changed

neutron/plugins/ml2/plugin.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,18 +1619,17 @@ def create_port_bulk(self, context, ports):
16191619
for port in port_list:
16201620
self._before_create_port(context, port)
16211621

1622-
port_list, net_cache = self.allocate_macs_and_ips_for_ports(
1623-
context, port_list)
1624-
16251622
try:
1623+
port_list, net_cache = self.allocate_macs_and_ips_for_ports(
1624+
context, port_list)
16261625
return self._create_port_bulk(context, port_list, net_cache)
16271626
except Exception:
16281627
with excutils.save_and_reraise_exception():
16291628
# If any issue happened allocated IP addresses needs to be
16301629
# deallocated now
16311630
for port in port_list:
16321631
self.ipam.deallocate_ips_from_port(
1633-
context, port, port['ipams'])
1632+
context, port, port.get('ipams'))
16341633

16351634
@db_api.retry_if_session_inactive()
16361635
def _create_port_bulk(self, context, port_list, network_cache):

neutron/tests/unit/plugins/ml2/test_plugin.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from neutron.db import provisioning_blocks
5656
from neutron.db import securitygroups_db as sg_db
5757
from neutron.db import segments_db
58+
from neutron.ipam import driver
5859
from neutron.objects import base as base_obj
5960
from neutron.objects import ports as port_obj
6061
from neutron.objects import router as l3_obj
@@ -1737,6 +1738,39 @@ def test_create_ports_bulk_with_extra_dhcp_opts(self):
17371738
ports_out = self.plugin.create_port_bulk(ctx, ports_in)
17381739
self.assertEqual(edo, ports_out[0]['extra_dhcp_opts'])
17391740

1741+
def test_create_ports_bulk_with_wrong_fixed_ips(self):
1742+
cidr = '10.0.10.0/24'
1743+
with self.network() as net:
1744+
with self.subnet(net, cidr=cidr) as snet:
1745+
net_id = net['network']['id']
1746+
data = [{'network_id': net_id,
1747+
'fixed_ips': [{'subnet_id': snet['subnet']['id'],
1748+
'ip_address': '10.0.10.100'}],
1749+
'tenant_id': snet['subnet']['tenant_id']
1750+
},
1751+
{'network_id': net_id,
1752+
'fixed_ips': [{'subnet_id': snet['subnet']['id'],
1753+
'ip_address': '10.0.20.101'}],
1754+
'tenant_id': snet['subnet']['tenant_id']
1755+
}]
1756+
res = self._create_bulk_from_list(self.fmt, 'port',
1757+
data, as_admin=True)
1758+
self.assertEqual(webob.exc.HTTPBadRequest.code, res.status_int)
1759+
self.assertIn('IP address 10.0.20.101 is not a valid IP for '
1760+
'the specified subnet.',
1761+
res.json['NeutronError']['message'])
1762+
1763+
ipam_driver = driver.Pool.get_instance(None, self.context)
1764+
ipam_allocator = ipam_driver.get_allocator([cidr])
1765+
with db_api.CONTEXT_READER.using(self.context):
1766+
ipam_subnet = ipam_allocator._driver.get_subnet(
1767+
snet['subnet']['id'])
1768+
allocations = ipam_subnet.subnet_manager.list_allocations(
1769+
self.context)
1770+
# There are no leftovers (e.g.: 10.0.10.100) in the
1771+
# "IpamAllocation" registers
1772+
self.assertEqual([], allocations)
1773+
17401774
def test_delete_port_no_notify_in_disassociate_floatingips(self):
17411775
ctx = context.get_admin_context()
17421776
plugin = directory.get_plugin()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
fixes:
3+
- |
4+
During the port bulk creation, if an IPAM allocation fails (for example, if
5+
the IP address is outside of the subnet CIDR), the other IPAM allocations
6+
already created are deleted before raising the exception. Fixes bug
7+
`2039550 <https://launchpad.net/bugs/2039550>`_.

0 commit comments

Comments
 (0)