diff --git a/quantum/plugins/linuxbridge/db/l2network_db_v2.py b/quantum/plugins/linuxbridge/db/l2network_db_v2.py index a481c9965..0a671852d 100644 --- a/quantum/plugins/linuxbridge/db/l2network_db_v2.py +++ b/quantum/plugins/linuxbridge/db/l2network_db_v2.py @@ -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(): + 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) - # 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)) + # 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""" diff --git a/quantum/plugins/openvswitch/ovs_db_v2.py b/quantum/plugins/openvswitch/ovs_db_v2.py index c1c4ebe23..5027ad396 100644 --- a/quantum/plugins/openvswitch/ovs_db_v2.py +++ b/quantum/plugins/openvswitch/ovs_db_v2.py @@ -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 - for physical_network, vlan_ranges in network_vlan_ranges.iteritems(): + # 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): diff --git a/quantum/tests/unit/linuxbridge/test_lb_db.py b/quantum/tests/unit/linuxbridge/test_lb_db.py index 6579b4c8d..f24fad2f0 100644 --- a/quantum/tests/unit/linuxbridge/test_lb_db.py +++ b/quantum/tests/unit/linuxbridge/test_lb_db.py @@ -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): diff --git a/quantum/tests/unit/openvswitch/test_ovs_db.py b/quantum/tests/unit/openvswitch/test_ovs_db.py index 6eab3d9cf..8ded7d888 100644 --- a/quantum/tests/unit/openvswitch/test_ovs_db.py +++ b/quantum/tests/unit/openvswitch/test_ovs_db.py @@ -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))