diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 31ba7c8f2de..db88b7fe5f5 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -592,6 +592,11 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2, def _allocate_fixed_ips(self, context, network, fixed_ips): """Allocate IP addresses according to the configured fixed_ips.""" ips = [] + + # we need to start with entries that asked for a specific IP in case + # those IPs happen to be next in the line for allocation for ones that + # didn't ask for a specific IP + fixed_ips.sort(key=lambda x: 'ip_address' not in x) for fixed in fixed_ips: if 'ip_address' in fixed: # Remove the IP address from the allocation pool diff --git a/neutron/tests/unit/test_db_plugin.py b/neutron/tests/unit/test_db_plugin.py index e7257b96d5e..cb0ccdbd7f1 100644 --- a/neutron/tests/unit/test_db_plugin.py +++ b/neutron/tests/unit/test_db_plugin.py @@ -853,6 +853,18 @@ class TestPortsV2(NeutronDbPluginV2TestCase): self.assertIn('mac_address', port['port']) self._delete('ports', port['port']['id']) + def test_create_port_anticipating_allocation(self): + with self.network(shared=True) as network: + with self.subnet(network=network, cidr='10.0.0.0/24') as subnet: + fixed_ips = [{'subnet_id': subnet['subnet']['id']}, + {'subnet_id': subnet['subnet']['id'], + 'ip_address': '10.0.0.2'}] + res = self._create_port(self.fmt, network['network']['id'], + webob.exc.HTTPCreated.code, + fixed_ips=fixed_ips) + self._delete('ports', + self.deserialize(self.fmt, res)['port']['id']) + def test_create_ports_bulk_native(self): if self._skip_native_bulk: self.skipTest("Plugin does not support native bulk port create")