]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fix OVS and LB plugins' VLAN allocation table synchronization
authorBob Kukura <rkukura@redhat.com>
Thu, 20 Sep 2012 20:03:14 +0000 (16:03 -0400)
committerBob Kukura <rkukura@redhat.com>
Fri, 21 Sep 2012 01:11:24 +0000 (21:11 -0400)
In both the openvswitch and linuxbridge plugins, if previous entries
for a physical network have been completely removed from the
network_vlan_ranges configuration variable, allocation table records
for unallocated VLANs on that physical network are now removed from
the DB at startup. The test_ovs_db and test_lb_db unit tests have also
been extended to cover this case. Fixes bug 1052289.

Test assertions that were added to the test_ovs_db unit test in
https://review.openstack.org/#/c/11388 have been added to the
test_lb_db unit test. Fixes bug 1045596.

Change-Id: I04e924603eaf0df717414c2aaa83fd203b791308

quantum/plugins/linuxbridge/db/l2network_db_v2.py
quantum/plugins/openvswitch/ovs_db_v2.py
quantum/tests/unit/linuxbridge/test_lb_db.py
quantum/tests/unit/openvswitch/test_ovs_db.py

index a481c99658654b79698978342b73e9e3e006ef86..0a671852d0928bc285dca439b4b00219b186eb5a 100644 (file)
@@ -40,23 +40,28 @@ def initialize():
 def sync_network_states(network_vlan_ranges):
     """Synchronize network_states table with current configured VLAN ranges."""
 
-    # process vlan ranges for each physical network separately
-    for physical_network, vlan_ranges in network_vlan_ranges.iteritems():
-
-        # determine current configured allocatable vlans for this
-        # physical network
-        vlan_ids = set()
-        for vlan_range in vlan_ranges:
-            vlan_ids |= set(xrange(vlan_range[0], vlan_range[1] + 1))
+    session = db.get_session()
+    with session.begin():
+        # get existing allocations for all physical networks
+        allocations = dict()
+        states = (session.query(l2network_models_v2.NetworkState).
+                  all())
+        for state in states:
+            if state.physical_network not in allocations:
+                allocations[state.physical_network] = set()
+            allocations[state.physical_network].add(state)
+
+        # process vlan ranges for each configured physical network
+        for physical_network, vlan_ranges in network_vlan_ranges.iteritems():
+            # determine current configured allocatable vlans for this
+            # physical network
+            vlan_ids = set()
+            for vlan_range in vlan_ranges:
+                vlan_ids |= set(xrange(vlan_range[0], vlan_range[1] + 1))
 
-        session = db.get_session()
-        with session.begin():
             # remove from table unallocated vlans not currently allocatable
-            try:
-                states = (session.query(l2network_models_v2.NetworkState).
-                          filter_by(physical_network=physical_network).
-                          all())
-                for state in states:
+            if physical_network in allocations:
+                for state in allocations[physical_network]:
                     try:
                         # see if vlan is allocatable
                         vlan_ids.remove(state.vlan_id)
@@ -68,8 +73,7 @@ def sync_network_states(network_vlan_ranges):
                                       "%s from pool" %
                                       (state.vlan_id, physical_network))
                             session.delete(state)
-            except exc.NoResultFound:
-                pass
+                del allocations[physical_network]
 
             # add missing allocatable vlans to table
             for vlan_id in sorted(vlan_ids):
@@ -77,6 +81,16 @@ def sync_network_states(network_vlan_ranges):
                                                          vlan_id)
                 session.add(state)
 
+        # remove from table unallocated vlans for any unconfigured physical
+        # networks
+        for states in allocations.itervalues():
+            for state in states:
+                if not state.allocated:
+                    LOG.debug("removing vlan %s on physical network %s"
+                              " from pool" %
+                              (state.vlan_id, physical_network))
+                    session.delete(state)
+
 
 def get_network_state(physical_network, vlan_id):
     """Get state of specified network"""
index c1c4ebe236eef1ce40d3d2e3d18adf1d7666fbc9..5027ad3967826a9f5bad6b735c8fa00c817b37d4 100644 (file)
@@ -64,9 +64,17 @@ def sync_vlan_allocations(network_vlan_ranges):
 
     session = db.get_session()
     with session.begin():
-        # process vlan ranges for each physical network separately
+        # get existing allocations for all physical networks
+        allocations = dict()
+        allocs = (session.query(ovs_models_v2.VlanAllocation).
+                  all())
+        for alloc in allocs:
+            if alloc.physical_network not in allocations:
+                allocations[alloc.physical_network] = set()
+            allocations[alloc.physical_network].add(alloc)
+
+        # process vlan ranges for each configured physical network
         for physical_network, vlan_ranges in network_vlan_ranges.iteritems():
-
             # determine current configured allocatable vlans for this
             # physical network
             vlan_ids = set()
@@ -74,11 +82,8 @@ def sync_vlan_allocations(network_vlan_ranges):
                 vlan_ids |= set(xrange(vlan_range[0], vlan_range[1] + 1))
 
             # remove from table unallocated vlans not currently allocatable
-            try:
-                allocs = (session.query(ovs_models_v2.VlanAllocation).
-                          filter_by(physical_network=physical_network).
-                          all())
-                for alloc in allocs:
+            if physical_network in allocations:
+                for alloc in allocations[physical_network]:
                     try:
                         # see if vlan is allocatable
                         vlan_ids.remove(alloc.vlan_id)
@@ -90,14 +95,23 @@ def sync_vlan_allocations(network_vlan_ranges):
                                       "%s from pool" %
                                       (alloc.vlan_id, physical_network))
                             session.delete(alloc)
-            except exc.NoResultFound:
-                pass
+                del allocations[physical_network]
 
             # add missing allocatable vlans to table
             for vlan_id in sorted(vlan_ids):
                 alloc = ovs_models_v2.VlanAllocation(physical_network, vlan_id)
                 session.add(alloc)
 
+        # remove from table unallocated vlans for any unconfigured physical
+        # networks
+        for allocs in allocations.itervalues():
+            for alloc in allocs:
+                if not alloc.allocated:
+                    LOG.debug("removing vlan %s on physical network %s"
+                              " from pool" %
+                              (alloc.vlan_id, physical_network))
+                    session.delete(alloc)
+
 
 def get_vlan_allocation(physical_network, vlan_id):
     session = db.get_session()
@@ -188,22 +202,19 @@ def sync_tunnel_allocations(tunnel_id_ranges):
     session = db.get_session()
     with session.begin():
         # remove from table unallocated tunnels not currently allocatable
-        try:
-            allocs = (session.query(ovs_models_v2.TunnelAllocation).
-                      all())
-            for alloc in allocs:
-                try:
-                    # see if tunnel is allocatable
-                    tunnel_ids.remove(alloc.tunnel_id)
-                except KeyError:
-                    # it's not allocatable, so check if its allocated
-                    if not alloc.allocated:
-                        # it's not, so remove it from table
-                        LOG.debug("removing tunnel %s from pool" %
-                                  alloc.tunnel_id)
-                        session.delete(alloc)
-        except exc.NoResultFound:
-            pass
+        allocs = (session.query(ovs_models_v2.TunnelAllocation).
+                  all())
+        for alloc in allocs:
+            try:
+                # see if tunnel is allocatable
+                tunnel_ids.remove(alloc.tunnel_id)
+            except KeyError:
+                # it's not allocatable, so check if its allocated
+                if not alloc.allocated:
+                    # it's not, so remove it from table
+                    LOG.debug("removing tunnel %s from pool" %
+                              alloc.tunnel_id)
+                    session.delete(alloc)
 
         # add missing allocatable tunnels to table
         for tunnel_id in sorted(tunnel_ids):
index 6579b4c8df2ea300dd8f7b042bcb1f7506d41e19..f24fad2f08b1eadedcafa6d33420112bee7af3aa 100644 (file)
@@ -20,10 +20,12 @@ from quantum.db import api as db
 from quantum.plugins.linuxbridge.db import l2network_db_v2 as lb_db
 
 PHYS_NET = 'physnet1'
+PHYS_NET_2 = 'physnet2'
 VLAN_MIN = 10
 VLAN_MAX = 19
 VLAN_RANGES = {PHYS_NET: [(VLAN_MIN, VLAN_MAX)]}
-UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)]}
+UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)],
+                       PHYS_NET_2: [(VLAN_MIN + 20, VLAN_MAX + 20)]}
 TEST_NETWORK_ID = 'abcdefghijklmnopqrstuvwxyz'
 
 
@@ -43,6 +45,8 @@ class NetworkStatesTest(unittest2.TestCase):
                                                  VLAN_MIN).allocated)
         self.assertFalse(lb_db.get_network_state(PHYS_NET,
                                                  VLAN_MIN + 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MAX - 1).allocated)
         self.assertFalse(lb_db.get_network_state(PHYS_NET,
                                                  VLAN_MAX).allocated)
         self.assertIsNone(lb_db.get_network_state(PHYS_NET,
@@ -56,11 +60,46 @@ class NetworkStatesTest(unittest2.TestCase):
                                                  VLAN_MIN + 5).allocated)
         self.assertFalse(lb_db.get_network_state(PHYS_NET,
                                                  VLAN_MIN + 5 + 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MAX + 5 - 1).allocated)
         self.assertFalse(lb_db.get_network_state(PHYS_NET,
                                                  VLAN_MAX + 5).allocated)
         self.assertIsNone(lb_db.get_network_state(PHYS_NET,
                                                   VLAN_MAX + 5 + 1))
 
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
+                                                  VLAN_MIN + 20 - 1))
+        self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
+                                                 VLAN_MIN + 20).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
+                                                 VLAN_MIN + 20 + 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
+                                                 VLAN_MAX + 20 - 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET_2,
+                                                 VLAN_MAX + 20).allocated)
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
+                                                  VLAN_MAX + 20 + 1))
+
+        lb_db.sync_network_states(VLAN_RANGES)
+
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET,
+                                                  VLAN_MIN - 1))
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MIN).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MIN + 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MAX - 1).allocated)
+        self.assertFalse(lb_db.get_network_state(PHYS_NET,
+                                                 VLAN_MAX).allocated)
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET,
+                                                  VLAN_MAX + 1))
+
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
+                                                  VLAN_MIN + 20))
+        self.assertIsNone(lb_db.get_network_state(PHYS_NET_2,
+                                                  VLAN_MAX + 20))
+
     def test_network_pool(self):
         vlan_ids = set()
         for x in xrange(VLAN_MIN, VLAN_MAX + 1):
index 6eab3d9cf6143c5e1cad713321f46232f6d91493..8ded7d8884f5efcab20f806382698f61e40cb8f4 100644 (file)
@@ -20,10 +20,12 @@ from quantum.db import api as db
 from quantum.plugins.openvswitch import ovs_db_v2
 
 PHYS_NET = 'physnet1'
+PHYS_NET_2 = 'physnet2'
 VLAN_MIN = 10
 VLAN_MAX = 19
 VLAN_RANGES = {PHYS_NET: [(VLAN_MIN, VLAN_MAX)]}
-UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)]}
+UPDATED_VLAN_RANGES = {PHYS_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)],
+                       PHYS_NET_2: [(VLAN_MIN + 20, VLAN_MAX + 20)]}
 TUN_MIN = 100
 TUN_MAX = 109
 TUNNEL_RANGES = [(TUN_MIN, TUN_MAX)]
@@ -47,6 +49,8 @@ class VlanAllocationsTest(unittest2.TestCase):
                                                        VLAN_MIN).allocated)
         self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
                                                        VLAN_MIN + 1).allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                       VLAN_MAX - 1).allocated)
         self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
                                                        VLAN_MAX).allocated)
         self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET,
@@ -71,6 +75,43 @@ class VlanAllocationsTest(unittest2.TestCase):
         self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET,
                                                         VLAN_MAX + 5 + 1))
 
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                        VLAN_MIN + 20 - 1))
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                       VLAN_MIN + 20).
+                         allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                       VLAN_MIN + 20 + 1).
+                         allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                       VLAN_MAX + 20 - 1).
+                         allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                       VLAN_MAX + 20).
+                         allocated)
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                        VLAN_MAX + 20 + 1))
+
+        ovs_db_v2.sync_vlan_allocations(VLAN_RANGES)
+
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                        VLAN_MIN - 1))
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                       VLAN_MIN).allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                       VLAN_MIN + 1).allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                       VLAN_MAX - 1).allocated)
+        self.assertFalse(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                       VLAN_MAX).allocated)
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET,
+                                                        VLAN_MAX + 1))
+
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                        VLAN_MIN + 20))
+        self.assertIsNone(ovs_db_v2.get_vlan_allocation(PHYS_NET_2,
+                                                        VLAN_MAX + 20))
+
     def test_vlan_pool(self):
         vlan_ids = set()
         for x in xrange(VLAN_MIN, VLAN_MAX + 1):
@@ -138,6 +179,8 @@ class TunnelAllocationsTest(unittest2.TestCase):
         self.assertFalse(ovs_db_v2.get_tunnel_allocation(TUN_MIN).allocated)
         self.assertFalse(ovs_db_v2.get_tunnel_allocation(TUN_MIN + 1).
                          allocated)
+        self.assertFalse(ovs_db_v2.get_tunnel_allocation(TUN_MAX - 1).
+                         allocated)
         self.assertFalse(ovs_db_v2.get_tunnel_allocation(TUN_MAX).allocated)
         self.assertIsNone(ovs_db_v2.get_tunnel_allocation(TUN_MAX + 1))