<s> import sys <EOL> from neutron_lib import exceptions as exc <EOL> from oslo_config import cfg <EOL> from oslo_log import log <EOL> from six import moves <EOL> import sqlalchemy as sa <EOL> from neutron . _i18n import _ , _LE , _LI , _LW <EOL> from neutron . db import api as db_api <EOL> from neutron . db import model_base <EOL> from neutron . plugins . common import constants as p_const <EOL> from neutron . plugins . common import utils as plugin_utils <EOL> from neutron . plugins . ml2 import driver_api as api <EOL> from neutron . plugins . ml2 . drivers import helpers <EOL> LOG = log . getLogger ( __name__ ) <EOL> vlan_opts = [ <EOL> cfg . ListOpt ( '<STR_LIT>' , <EOL> default = [ ] , <EOL> help = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> ] <EOL> cfg . CONF . register_opts ( vlan_opts , "<STR_LIT>" ) <EOL> class VlanAllocation ( model_base . BASEV2 ) : <EOL> """<STR_LIT>""" <EOL> __tablename__ = '<STR_LIT>' <EOL> __table_args__ = ( <EOL> sa . Index ( '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' ) , <EOL> model_base . BASEV2 . __table_args__ , ) <EOL> physical_network = sa . Column ( sa . String ( <NUM_LIT:64> ) , nullable = False , <EOL> primary_key = True ) <EOL> vlan_id = sa . Column ( sa . Integer , nullable = False , primary_key = True , <EOL> autoincrement = False ) <EOL> allocated = sa . Column ( sa . Boolean , nullable = False ) <EOL> class VlanTypeDriver ( helpers . SegmentTypeDriver ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> super ( VlanTypeDriver , self ) . __init__ ( VlanAllocation ) <EOL> self . _parse_network_vlan_ranges ( ) <EOL> def _parse_network_vlan_ranges ( self ) : <EOL> try : <EOL> self . network_vlan_ranges = plugin_utils . parse_network_vlan_ranges ( <EOL> cfg . CONF . ml2_type_vlan . network_vlan_ranges ) <EOL> except Exception : <EOL> LOG . exception ( _LE ( "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> sys . exit ( <NUM_LIT:1> ) <EOL> LOG . info ( _LI ( "<STR_LIT>" ) , self . network_vlan_ranges ) <EOL> def _sync_vlan_allocations ( self ) : <EOL> session = db_api . get_session ( ) <EOL> with session . begin ( subtransactions = True ) : <EOL> allocations = dict ( ) <EOL> allocs = ( session . query ( VlanAllocation ) . <EOL> with_lockmode ( '<STR_LIT>' ) ) <EOL> for alloc in allocs : <EOL> if alloc . physical_network not in allocations : <EOL> allocations [ alloc . physical_network ] = set ( ) <EOL> allocations [ alloc . physical_network ] . add ( alloc ) <EOL> for ( physical_network , <EOL> vlan_ranges ) in self . network_vlan_ranges . items ( ) : <EOL> vlan_ids = set ( ) <EOL> for vlan_min , vlan_max in vlan_ranges : <EOL> vlan_ids |= set ( moves . range ( vlan_min , vlan_max + <NUM_LIT:1> ) ) <EOL> if physical_network in allocations : <EOL> for alloc in allocations [ physical_network ] : <EOL> try : <EOL> vlan_ids . remove ( alloc . vlan_id ) <EOL> except KeyError : <EOL> if not alloc . allocated : <EOL> LOG . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> { '<STR_LIT>' : alloc . vlan_id , <EOL> '<STR_LIT>' : <EOL> physical_network } ) <EOL> session . delete ( alloc ) <EOL> del allocations [ physical_network ] <EOL> for vlan_id in sorted ( vlan_ids ) : <EOL> alloc = VlanAllocation ( physical_network = physical_network , <EOL> vlan_id = vlan_id , <EOL> allocated = False ) <EOL> session . add ( alloc ) <EOL> for allocs in allocations . values ( ) : <EOL> for alloc in allocs : <EOL> if not alloc . allocated : <EOL> LOG . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> { '<STR_LIT>' : alloc . vlan_id , <EOL> '<STR_LIT>' : <EOL> alloc . physical_network } ) <EOL> session . delete ( alloc ) <EOL> def get_type ( self ) : <EOL> return p_const . TYPE_VLAN <EOL> def initialize ( self ) : <EOL> self . _sync_vlan_allocations ( ) <EOL> LOG . info ( _LI ( "<STR_LIT>" ) ) <EOL> def is_partial_segment ( self , segment ) : <EOL> return segment . get ( api . SEGMENTATION_ID ) is None <EOL> def validate_provider_segment ( self , segment ) : <EOL> physical_network = segment . get ( api . PHYSICAL_NETWORK ) <EOL> segmentation_id = segment . get ( api . SEGMENTATION_ID ) <EOL> if physical_network : <EOL> if physical_network not in self . network_vlan_ranges : <EOL> msg = ( _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % physical_network ) <EOL> raise exc . InvalidInput ( error_message = msg ) <EOL> if segmentation_id : <EOL> if not plugin_utils . is_valid_vlan_tag ( segmentation_id ) : <EOL> msg = ( _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) % <EOL> { '<STR_LIT>' : p_const . MIN_VLAN_TAG , <EOL> '<STR_LIT>' : p_const . MAX_VLAN_TAG } ) <EOL> raise exc . InvalidInput ( error_message = msg ) <EOL> elif segmentation_id : <EOL> msg = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> raise exc . InvalidInput ( error_message = msg ) <EOL> for key , value in segment . items ( ) : <EOL> if value and key not in [ api . NETWORK_TYPE , <EOL> api . PHYSICAL_NETWORK , <EOL> api . SEGMENTATION_ID ] : <EOL> msg = _ ( "<STR_LIT>" ) % key <EOL> raise exc . InvalidInput ( error_message = msg ) <EOL> def reserve_provider_segment ( self , session , segment ) : <EOL> filters = { } <EOL> physical_network = segment . get ( api . PHYSICAL_NETWORK ) <EOL> if physical_network is not None : <EOL> filters [ '<STR_LIT>' ] = physical_network <EOL> vlan_id = segment . get ( api . SEGMENTATION_ID ) <EOL> if vlan_id is not None : <EOL> filters [ '<STR_LIT>' ] = vlan_id <EOL> if self . is_partial_segment ( segment ) : <EOL> alloc = self . allocate_partially_specified_segment ( <EOL> session , ** filters ) <EOL> if not alloc : <EOL> raise exc . NoNetworkAvailable ( ) <EOL> else : <EOL> alloc = self . allocate_fully_specified_segment ( <EOL> session , ** filters ) <EOL> if not alloc : <EOL> raise exc . VlanIdInUse ( ** filters ) <EOL> return { api . NETWORK_TYPE : p_const . TYPE_VLAN , <EOL> api . PHYSICAL_NETWORK : alloc . physical_network , <EOL> api . SEGMENTATION_ID : alloc . vlan_id , <EOL> api . MTU : self . get_mtu ( alloc . physical_network ) } <EOL> def allocate_tenant_segment ( self , session ) : <EOL> alloc = self . allocate_partially_specified_segment ( session ) <EOL> if not alloc : <EOL> return <EOL> return { api . NETWORK_TYPE : p_const . TYPE_VLAN , <EOL> api . PHYSICAL_NETWORK : alloc . physical_network , <EOL> api . SEGMENTATION_ID : alloc . vlan_id , <EOL> api . MTU : self . get_mtu ( alloc . physical_network ) } <EOL> def release_segment ( self , session , segment ) : <EOL> physical_network = segment [ api . PHYSICAL_NETWORK ] <EOL> vlan_id = segment [ api . SEGMENTATION_ID ] <EOL> ranges = self . network_vlan_ranges . get ( physical_network , [ ] ) <EOL> inside = any ( lo <= vlan_id <= hi for lo , hi in ranges ) <EOL> with session . begin ( subtransactions = True ) : <EOL> query = ( session . query ( VlanAllocation ) . <EOL> filter_by ( physical_network = physical_network , <EOL> vlan_id = vlan_id ) ) <EOL> if inside : <EOL> count = query . update ( { "<STR_LIT>" : False } ) <EOL> if count : <EOL> LOG . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> { '<STR_LIT>' : vlan_id , <EOL> '<STR_LIT>' : physical_network } ) <EOL> else : <EOL> count = query . delete ( ) <EOL> if count : <EOL> LOG . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> { '<STR_LIT>' : vlan_id , <EOL> '<STR_LIT>' : physical_network } ) <EOL> if not count : <EOL> LOG . warning ( _LW ( "<STR_LIT>" <EOL> "<STR_LIT>" ) , <EOL> { '<STR_LIT>' : vlan_id , <EOL> '<STR_LIT>' : physical_network } ) <EOL> def get_mtu ( self , physical_network ) : <EOL> seg_mtu = super ( VlanTypeDriver , self ) . get_mtu ( ) <EOL> mtu = [ ] <EOL> if seg_mtu > <NUM_LIT:0> : <EOL> mtu . append ( seg_mtu ) <EOL> if physical_network in self . physnet_mtus : <EOL> mtu . append ( int ( self . physnet_mtus [ physical_network ] ) ) <EOL> return min ( mtu ) if mtu else <NUM_LIT:0> </s>
