]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Process port IP requests before subnet requests
authorKevin Benton <blak111@gmail.com>
Thu, 28 May 2015 00:38:32 +0000 (17:38 -0700)
committerKevin Benton <kevinbenton@buttewifi.com>
Thu, 28 May 2015 23:16:24 +0000 (23:16 +0000)
When a port requests multiple fixed IPs, process the requests
for specific IP addresses before the ones asking for a subnet.
This prevents an error where the IP that was requested happens
to be the next up for allocation so the subnet request takes it
and causes a DBDuplicateEntry.

Closes-Bug: #1459467
Change-Id: I645565c7fe0c47c58d686b25020bb49a0b9089f5
(cherry picked from commit 817b45b6406d9730859535ac54d73ec5c85451d0)

neutron/db/db_base_plugin_v2.py
neutron/tests/unit/db/test_db_base_plugin_v2.py

index 24c251340b7df0ca2819a39b436c4f1ae5b7b5aa..e75dd4cbb18c7d980ab369e88512db5fb8cdc038 100644 (file)
@@ -458,6 +458,11 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
     def _allocate_fixed_ips(self, context, fixed_ips, mac_address):
         """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:
             subnet = self._get_subnet(context, fixed['subnet_id'])
             is_auto_addr = ipv6_utils.is_auto_address_subnet(subnet)
index 0804e9047d9da12a1e3dc9dc3bb8d87cbf7c132f..ec97c9aed9a6136c6e29029969094ce59357b31a 100644 (file)
@@ -909,6 +909,16 @@ 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'}]
+                self._create_port(self.fmt, network['network']['id'],
+                                  webob.exc.HTTPCreated.code,
+                                  fixed_ips=fixed_ips)
+
     def test_create_port_public_network_with_invalid_ip_no_subnet_id(self,
             expected_error='InvalidIpForNetwork'):
         with self.network(shared=True) as network: