]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix neutron hang for IPv6 allocation pool update
authorsridhargaddam <sridhar.gaddam@enovance.com>
Mon, 15 Dec 2014 11:11:15 +0000 (11:11 +0000)
committersridhargaddam <sridhar.gaddam@enovance.com>
Mon, 15 Dec 2014 11:11:26 +0000 (11:11 +0000)
While rebuilding IPAllocationPools, Neutron is using netaddr.iter_iprange
(a generator that produces IPAddress objects). For an IPv6 subnet, this is
a costly operation and is causing Neutron Server to hang. This patch
addresses the issue by replacing netaddr.iter_iprange with netaddr.IPRange
which provides the same functionality while calculating the IPSets.

Closes-Bug: #1401751
Change-Id: I2287e5348aab82e39cf1b6e2884d08237a09b06d

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

index 6f062fcafb11c3e152627a7f3fe120c38af37517..37ad8b7587bbaee60655f1c8fe6c41fd7927da3e 100644 (file)
@@ -268,8 +268,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
 
             for pool in pool_qry.filter_by(subnet_id=subnet['id']):
                 # Create a set of all addresses in the pool
-                poolset = netaddr.IPSet(netaddr.iter_iprange(pool['first_ip'],
-                                                             pool['last_ip']))
+                poolset = netaddr.IPSet(netaddr.IPRange(pool['first_ip'],
+                                                        pool['last_ip']))
 
                 # Use set difference to find free addresses in the pool
                 available = poolset - allocations
index f1f54c3a146fda8733b9bffb42fc7294910a0732..ac98d7d8ab61bce477c141669fe7bcd7e3dc8b35 100644 (file)
@@ -4062,22 +4062,8 @@ class TestNeutronDbPluginV2(base.BaseTestCase):
         self.assertEqual(2, generate.call_count)
         rebuild.assert_called_once_with('c', 's')
 
-    def test_rebuild_availability_ranges(self):
-        pools = [{'id': 'a',
-                  'first_ip': '192.168.1.3',
-                  'last_ip': '192.168.1.10'},
-                 {'id': 'b',
-                  'first_ip': '192.168.1.100',
-                  'last_ip': '192.168.1.120'}]
-
-        allocations = [{'ip_address': '192.168.1.3'},
-                       {'ip_address': '192.168.1.78'},
-                       {'ip_address': '192.168.1.7'},
-                       {'ip_address': '192.168.1.110'},
-                       {'ip_address': '192.168.1.11'},
-                       {'ip_address': '192.168.1.4'},
-                       {'ip_address': '192.168.1.111'}]
-
+    def _validate_rebuild_availability_ranges(self, pools, allocations,
+                                              expected):
         ip_qry = mock.Mock()
         ip_qry.with_lockmode.return_value = ip_qry
         ip_qry.filter_by.return_value = allocations
@@ -4103,11 +4089,61 @@ class TestNeutronDbPluginV2(base.BaseTestCase):
         actual = [[args[0].allocation_pool_id,
                    args[0].first_ip, args[0].last_ip]
                   for _name, args, _kwargs in context.session.add.mock_calls]
+        self.assertEqual(expected, actual)
+
+    def test_rebuild_availability_ranges(self):
+        pools = [{'id': 'a',
+                  'first_ip': '192.168.1.3',
+                  'last_ip': '192.168.1.10'},
+                 {'id': 'b',
+                  'first_ip': '192.168.1.100',
+                  'last_ip': '192.168.1.120'}]
+
+        allocations = [{'ip_address': '192.168.1.3'},
+                       {'ip_address': '192.168.1.78'},
+                       {'ip_address': '192.168.1.7'},
+                       {'ip_address': '192.168.1.110'},
+                       {'ip_address': '192.168.1.11'},
+                       {'ip_address': '192.168.1.4'},
+                       {'ip_address': '192.168.1.111'}]
 
-        self.assertEqual([['a', '192.168.1.5', '192.168.1.6'],
-                          ['a', '192.168.1.8', '192.168.1.10'],
-                          ['b', '192.168.1.100', '192.168.1.109'],
-                          ['b', '192.168.1.112', '192.168.1.120']], actual)
+        expected = [['a', '192.168.1.5', '192.168.1.6'],
+                    ['a', '192.168.1.8', '192.168.1.10'],
+                    ['b', '192.168.1.100', '192.168.1.109'],
+                    ['b', '192.168.1.112', '192.168.1.120']]
+
+        self._validate_rebuild_availability_ranges(pools, allocations,
+                                                   expected)
+
+    def test_rebuild_ipv6_availability_ranges(self):
+        pools = [{'id': 'a',
+                  'first_ip': '2001::1',
+                  'last_ip': '2001::50'},
+                 {'id': 'b',
+                  'first_ip': '2001::100',
+                  'last_ip': '2001::ffff:ffff:ffff:fffe'}]
+
+        allocations = [{'ip_address': '2001::10'},
+                       {'ip_address': '2001::45'},
+                       {'ip_address': '2001::60'},
+                       {'ip_address': '2001::111'},
+                       {'ip_address': '2001::200'},
+                       {'ip_address': '2001::ffff:ffff:ffff:ff10'},
+                       {'ip_address': '2001::ffff:ffff:ffff:f2f0'}]
+
+        expected = [['a', '2001::1', '2001::f'],
+                    ['a', '2001::11', '2001::44'],
+                    ['a', '2001::46', '2001::50'],
+                    ['b', '2001::100', '2001::110'],
+                    ['b', '2001::112', '2001::1ff'],
+                    ['b', '2001::201', '2001::ffff:ffff:ffff:f2ef'],
+                    ['b', '2001::ffff:ffff:ffff:f2f1',
+                     '2001::ffff:ffff:ffff:ff0f'],
+                    ['b', '2001::ffff:ffff:ffff:ff11',
+                     '2001::ffff:ffff:ffff:fffe']]
+
+        self._validate_rebuild_availability_ranges(pools, allocations,
+                                                   expected)
 
 
 class NeutronDbPluginV2AsMixinTestCase(testlib_api.SqlTestCase):