def synchronize(self): LOG.info(_LI('Syncing VLANs with EOS')) try: self._rpc.register_with_eos() vlan_pool = self._rpc.get_vlan_allocation() except arista_exc.AristaRpcError: LOG.warning(EOS_UNREACHABLE_MSG) self._force_sync = True return self._assigned_vlans = { 'default': self._parse_vlan_ranges(vlan_pool['assignedVlans'], return_as_ranges=True), } assigned_vlans = (self._parse_vlan_ranges(vlan_pool['assignedVlans'])) available_vlans = frozenset( self._parse_vlan_ranges(vlan_pool['availableVlans'])) used_vlans = frozenset( self._parse_vlan_ranges(vlan_pool['allocatedVlans'])) self._force_sync = False session = db_api.get_writer_session() with session.begin(subtransactions=True): allocs = (session.query( vlanallocation.VlanAllocation).with_lockmode('update')) for alloc in allocs: if alloc.physical_network != 'default': session.delete(alloc) try: assigned_vlans.remove(alloc.vlan_id) except KeyError: session.delete(alloc) continue if alloc.allocated and alloc.vlan_id in available_vlans: alloc.update({"allocated": False}) elif not alloc.allocated and alloc.vlan_id in used_vlans: alloc.update({"allocated": True}) for vlan_id in sorted(assigned_vlans): allocated = vlan_id in used_vlans alloc = vlanallocation.VlanAllocation( physical_network='default', vlan_id=vlan_id, allocated=allocated) session.add(alloc)
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 = ctx.session.query(vlan_alloc_model.VlanAllocation) 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 self.network_vlan_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)) # remove from table unallocated vlans not currently # allocatable if physical_network in allocations: for alloc in allocations[physical_network]: try: # see if vlan is allocatable vlan_ids.remove(alloc.vlan_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 vlan %(vlan_id)s on " "physical network " "%(physical_network)s from pool", { 'vlan_id': alloc.vlan_id, 'physical_network': physical_network }) # This UPDATE WHERE statement blocks anyone # from concurrently changing the allocation # values to True while our transaction is # open so we don't accidentally delete # allocated segments. If someone has already # allocated, count will return 0 so we don't # delete. count = allocs.filter_by( allocated=False, vlan_id=alloc.vlan_id, physical_network=physical_network).update( {"allocated": False}) if count: ctx.session.delete(alloc) del allocations[physical_network] # add missing allocatable vlans to table for vlan_id in sorted(vlan_ids): alloc = vlan_alloc_model.VlanAllocation( physical_network=physical_network, vlan_id=vlan_id, allocated=False) ctx.session.add(alloc) # 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 }) ctx.session.delete(alloc)
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 = (ctx.session.query( vlan_alloc_model.VlanAllocation).with_lockmode('update')) 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 self.network_vlan_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)) # remove from table unallocated vlans not currently # allocatable if physical_network in allocations: for alloc in allocations[physical_network]: try: # see if vlan is allocatable vlan_ids.remove(alloc.vlan_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 vlan %(vlan_id)s on " "physical network " "%(physical_network)s from pool", { 'vlan_id': alloc.vlan_id, 'physical_network': physical_network }) ctx.session.delete(alloc) del allocations[physical_network] # add missing allocatable vlans to table for vlan_id in sorted(vlan_ids): alloc = vlan_alloc_model.VlanAllocation( physical_network=physical_network, vlan_id=vlan_id, allocated=False) ctx.session.add(alloc) # 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 }) ctx.session.delete(alloc)