Browse Source

Merge "Improve VLAN allocations synchronization" into stable/rocky

changes/45/726245/1
Zuul 3 months ago
committed by Gerrit Code Review
parent
commit
b9a3e0f68e
3 changed files with 61 additions and 30 deletions
  1. +21
    -0
      neutron/objects/plugins/ml2/vlanallocation.py
  2. +22
    -30
      neutron/plugins/ml2/drivers/type_vlan.py
  3. +18
    -0
      neutron/tests/unit/plugins/ml2/drivers/test_type_vlan.py

+ 21
- 0
neutron/objects/plugins/ml2/vlanallocation.py View File

@@ -33,3 +33,24 @@ class VlanAllocation(base.NeutronDbObject):
}

primary_keys = ['physical_network', 'vlan_id']

@staticmethod
def get_physical_networks(context):
query = context.session.query(VlanAllocation.db_model.physical_network)
query = query.group_by(VlanAllocation.db_model.physical_network)
physnets = query.all()
return {physnet.physical_network for physnet in physnets}

@staticmethod
def delete_physical_networks(context, physical_networks):
column = VlanAllocation.db_model.physical_network
context.session.query(VlanAllocation.db_model).filter(
column.in_(physical_networks)).delete(synchronize_session=False)

@staticmethod
def bulk_create(ctx, physical_network, vlan_ids):
ctx.session.bulk_insert_mappings(
vlan_alloc_model.VlanAllocation,
[{'physical_network': physical_network,
'allocated': False,
'vlan_id': vlan_id} for vlan_id in vlan_ids])

+ 22
- 30
neutron/plugins/ml2/drivers/type_vlan.py View File

@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.

import collections
import sys

from neutron_lib import constants as p_const
@@ -23,7 +24,6 @@ from neutron_lib.plugins.ml2 import api
from neutron_lib.plugins import utils as plugin_utils
from oslo_config import cfg
from oslo_log import log
from six import moves

from neutron._i18n import _
from neutron.conf.plugins.ml2.drivers import driver_type
@@ -65,22 +65,30 @@ class VlanTypeDriver(helpers.SegmentTypeDriver):
def _sync_vlan_allocations(self):
ctx = context.get_admin_context()
with db_api.context_manager.writer.using(ctx):
# get existing allocations for all physical networks
allocations = dict()
allocs = vlanalloc.VlanAllocation.get_objects(ctx)
for alloc in allocs:
if alloc.physical_network not in allocations:
allocations[alloc.physical_network] = list()
# VLAN ranges per physical network:
# {phy1: [(1, 10), (30, 50)], ...}
ranges = self.network_vlan_ranges

# Delete those VLAN registers from unconfigured physical networks
physnets = vlanalloc.VlanAllocation.get_physical_networks(ctx)
physnets_unconfigured = physnets - set(ranges)
if physnets_unconfigured:
LOG.debug('Removing any VLAN register on physical networks %s',
physnets_unconfigured)
vlanalloc.VlanAllocation.delete_physical_networks(
ctx, physnets_unconfigured)

# Get existing allocations for all configured physical networks
allocations = collections.defaultdict(list)
for alloc in vlanalloc.VlanAllocation.get_objects(ctx):
allocations[alloc.physical_network].append(alloc)

# process vlan ranges for each configured physical network
for (physical_network,
vlan_ranges) in self.network_vlan_ranges.items():
for physical_network, vlan_ranges in ranges.items():
# determine current configured allocatable vlans for
# this physical network
vlan_ids = set()
for vlan_min, vlan_max in vlan_ranges:
vlan_ids |= set(moves.range(vlan_min, vlan_max + 1))
vlan_ids |= set(range(vlan_min, vlan_max + 1))

# remove from table unallocated vlans not currently
# allocatable
@@ -113,25 +121,9 @@ class VlanTypeDriver(helpers.SegmentTypeDriver):
alloc.delete()
del allocations[physical_network]

# add missing allocatable vlans to table
for vlan_id in sorted(vlan_ids):
alloc = vlanalloc.VlanAllocation(
ctx,
physical_network=physical_network,
vlan_id=vlan_id, allocated=False)
alloc.create()

# remove from table unallocated vlans for any unconfigured
# physical networks
for allocs in allocations.values():
for alloc in allocs:
if not alloc.allocated:
LOG.debug("Removing vlan %(vlan_id)s on physical "
"network %(physical_network)s from pool",
{'vlan_id': alloc.vlan_id,
'physical_network':
alloc.physical_network})
alloc.delete()
# Add missing allocatable VLAN registers for "physical_network"
vlanalloc.VlanAllocation.bulk_create(ctx, physical_network,
vlan_ids)

def get_type(self):
return p_const.TYPE_VLAN


+ 18
- 0
neutron/tests/unit/plugins/ml2/drivers/test_type_vlan.py View File

@@ -29,6 +29,7 @@ from neutron.tests.unit import testlib_api

PROVIDER_NET = 'phys_net1'
TENANT_NET = 'phys_net2'
UNCONFIGURED_NET = 'no_net'
VLAN_MIN = 200
VLAN_MAX = 209
NETWORK_VLAN_RANGES = [PROVIDER_NET, "%s:%s:%s" %
@@ -40,6 +41,12 @@ UPDATED_VLAN_RANGES = {
EMPTY_VLAN_RANGES = {
PROVIDER_NET: []
}
NETWORK_VLAN_RANGES_WITH_UNCONFIG = {
PROVIDER_NET: [],
TENANT_NET: [(VLAN_MIN + 5, VLAN_MAX + 5)],
UNCONFIGURED_NET: [(VLAN_MIN, VLAN_MAX)]
}

CORE_PLUGIN = 'ml2'


@@ -168,10 +175,21 @@ class VlanTypeTest(testlib_api.SqlTestCase):
self._get_allocation(self.context, segment).allocated)

check_in_ranges(self.network_vlan_ranges)

self.driver.network_vlan_ranges = UPDATED_VLAN_RANGES
self.driver._sync_vlan_allocations()
check_in_ranges(UPDATED_VLAN_RANGES)

self.driver.network_vlan_ranges = NETWORK_VLAN_RANGES_WITH_UNCONFIG
self.driver._sync_vlan_allocations()
self.driver.network_vlan_ranges = UPDATED_VLAN_RANGES
with mock.patch.object(type_vlan.LOG, 'debug') as mock_debug:
self.driver._sync_vlan_allocations()
mock_debug.assert_called_once_with(
'Removing any VLAN register on physical networks %s',
{UNCONFIGURED_NET})
check_in_ranges(UPDATED_VLAN_RANGES)

self.driver.network_vlan_ranges = EMPTY_VLAN_RANGES
self.driver._sync_vlan_allocations()



Loading…
Cancel
Save