from vlcp.server.module import Module, publicapi
from vlcp.event.runnable import RoutineContainer
from vlcp.utils.networkmodel import PhysicalNetworkMap, PhysicalNetwork,\
    VXLANEndpointSet
from vlcp.config.config import defaultconfig
from vlcp.utils.networkplugin import createphysicalnetwork,\
    updatephysicalnetwork, default_physicalnetwork_keys, deletephysicalnetwork,\
    deletephysicalport, default_physicalport_keys, createlogicalnetwork,\
    default_logicalnetwork_keys, default_processor, updatelogicalnetwork,\
    deletelogicalnetwork, createphysicalport, updatephysicalport,\
    default_logicalnetwork_delete_check
from vlcp.utils.exceptions import WalkKeyNotRetrieved
from vlcp.utils.walkerlib import ensure_keys


@defaultconfig
class NetworkVxlanDriver(Module):
    """
    Network driver for VXLAN networks. When creating a VXLAN type physical network,
    you must specify an extra option ``vnirange``.
    """
    def __init__(self,server):
        super(NetworkVxlanDriver,self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(
                       publicapi(self.createphysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatephysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletephysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.createphysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatephysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletephysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.createlogicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatelogicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletelogicalnetwork,
                                    criteria=lambda type: type == "vxlan")
                       )

    async def _main(self):
        self._logger.info("network_vxlan_driver running ---")

    def createphysicalnetwork(self, type):
        # create an new physical network
        def create_physicalnetwork_processor(physicalnetwork, walk, write, *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError('must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters, excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=create_physicalnetwork_processor),\
                default_physicalnetwork_keys

    def updatephysicalnetwork(self, type):
        # update a physical network
        def update_physicalnetwork_keys(id_, parameters):
            if 'vnirange' in parameters:
                return (PhysicalNetworkMap.default_key(id_),)
            else:
                return ()
        def update_physicalnetwork_processor(physicalnetwork, walk, write, *, parameters):
            if 'vnirange' in parameters:
                _check_vnirange(parameters['vnirange'])
                try:
                    phymap = walk(PhysicalNetworkMap.default_key(physicalnetwork.id))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    _check_vnirange_allocation(parameters['vnirange'], phymap.network_allocation)
            return default_processor(physicalnetwork, parameters=parameters, disabled=('type',))
        return updatephysicalnetwork(update_processor=update_physicalnetwork_processor), update_physicalnetwork_keys

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None

    def deletephysicalport(self, type):
        return deletephysicalport(), default_physicalport_keys

    def createlogicalnetwork(self, type):
        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap, physicalnetwork,
                                     physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                # Allocate this vni
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange, physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError("Specified VNI " + str(vni) + " allocated or not in range")
            else:
                # Allocate a vni from range
                vni = _findavaliablevni(physicalnetwork.vnirange, physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError("no available VNI in physical network " + physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            # Create VXLANEndpointSet
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork.id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters, excluding=('id', 'physicalnetwork', 'vni'))
        # Process logical networks with specified IDs first
        return createlogicalnetwork(create_processor=logicalnetwork_processor,
                                    reorder_dict=lambda x: sorted(x.items(), key=lambda y: 'vni' in y[1], reverse=True)),\
               default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):
        # When updating VLAN ids, Must first deallocate all VLAN ids, then allocate all
        # Chaining two walkers for this
        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return (PhysicalNetwork.default_key(id_),
                        PhysicalNetworkMap.default_key(id_))
            else:
                return ()
        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=deallocate_processor)
        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.network_allocation, vni):
                        phymap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError("Specified VNI " + str(vni) + " allocated or not in range")
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters, excluding=('id', 'vni'),
                                                                            disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=allocate_processor)
        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):
        def check_processor(logicalnetwork, logicalnetworkmap,
                            physicalnetwork, physicalnetworkmap,
                            walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork, logicalnetworkmap,
                                                physicalnetwork, physicalnetworkmap,
                                                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor), default_logicalnetwork_keys


def _check_vnirange(vnirange):
    lastend = 0
    for start,end in vnirange:
        if start <= 0 or end > (1 << 24) - 1:
            raise ValueError('VNI out of range (1 - 4095)')
        if start > end or start <= lastend:
            raise ValueError('VNI sequences overlapped or disordered: [%r, %r]' % (start, end))
        lastend = end


def _check_vnirange_allocation(vnirange, allocation):
    allocated_ids = sorted(int(k) for k in allocation.keys())
    range_iter = iter(vnirange)
    current_range = None
    for id_ in allocated_ids:
        while current_range is None or current_range[1] < id_:
            try:
                current_range = next(range_iter)
            except StopIteration:
                raise ValueError("Allocated VNI " + str(id_) + " not in new VNI range")
        if current_range[0] > id_:
            raise ValueError("Allocated VNI " + str(id_) + " not in new VNI range")


def _findavaliablevni(vnirange,allocated):
    
    vni = None
    for vr in vnirange:
        find = False
        for v in range(vr[0],vr[1] + 1):
            if str(v) not in allocated:
                vni = v
                find = True
                break

        if find:
            break
    return vni


def _isavaliablevni(vnirange,allocated,vni):
    
    find = False
    for start,end in vnirange:
        if start <= int(vni) <= end:
            find = True
            break

    if find:
        if str(vni) not in allocated:
            find = True
        else:
            find = False
    else:
        find = False

    return find

b9c5ee4bba158039605fb5a14c3784f91ea9e2a8
<mask token>


@defaultconfig
class NetworkVxlanDriver(Module):
    <mask token>

    def __init__(self, server):
        super(NetworkVxlanDriver, self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(publicapi(self.createphysicalnetwork, criteria=lambda
            type: type == 'vxlan'), publicapi(self.updatephysicalnetwork,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            deletephysicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.createphysicalport, criteria=lambda type: type ==
            'vxlan'), publicapi(self.updatephysicalport, criteria=lambda
            type: type == 'vxlan'), publicapi(self.deletephysicalport,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            createlogicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.updatelogicalnetwork, criteria=lambda type: type ==
            'vxlan'), publicapi(self.deletelogicalnetwork, criteria=lambda
            type: type == 'vxlan'))

    async def _main(self):
        self._logger.info('network_vxlan_driver running ---')

    def createphysicalnetwork(self, type):

        def create_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError(
                    'must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters,
                excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=
            create_physicalnetwork_processor), default_physicalnetwork_keys
    <mask token>

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None
    <mask token>

    def createlogicalnetwork(self, type):

        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)
                        ] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError('Specified VNI ' + str(vni) +
                        ' allocated or not in range')
            else:
                vni = _findavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError(
                        'no available VNI in physical network ' +
                        physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)
                    ] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork
                .id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'physicalnetwork', 'vni'))
        return createlogicalnetwork(create_processor=
            logicalnetwork_processor, reorder_dict=lambda x: sorted(x.items
            (), key=lambda y: 'vni' in y[1], reverse=True)
            ), default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):

        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return PhysicalNetwork.default_key(id_
                    ), PhysicalNetworkMap.default_key(id_)
            else:
                return ()

        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=
            deallocate_processor)

        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.
                        network_allocation, vni):
                        phymap.network_allocation[str(vni)
                            ] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError('Specified VNI ' + str(vni) +
                            ' allocated or not in range')
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'vni'), disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=
            allocate_processor)

        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):

        def check_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork,
                logicalnetworkmap, physicalnetwork, physicalnetworkmap,
                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor
            ), default_logicalnetwork_keys


<mask token>

<mask token>


@defaultconfig
class NetworkVxlanDriver(Module):
    """
    Network driver for VXLAN networks. When creating a VXLAN type physical network,
    you must specify an extra option ``vnirange``.
    """

    def __init__(self, server):
        super(NetworkVxlanDriver, self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(publicapi(self.createphysicalnetwork, criteria=lambda
            type: type == 'vxlan'), publicapi(self.updatephysicalnetwork,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            deletephysicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.createphysicalport, criteria=lambda type: type ==
            'vxlan'), publicapi(self.updatephysicalport, criteria=lambda
            type: type == 'vxlan'), publicapi(self.deletephysicalport,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            createlogicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.updatelogicalnetwork, criteria=lambda type: type ==
            'vxlan'), publicapi(self.deletelogicalnetwork, criteria=lambda
            type: type == 'vxlan'))

    async def _main(self):
        self._logger.info('network_vxlan_driver running ---')

    def createphysicalnetwork(self, type):

        def create_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError(
                    'must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters,
                excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=
            create_physicalnetwork_processor), default_physicalnetwork_keys

    def updatephysicalnetwork(self, type):

        def update_physicalnetwork_keys(id_, parameters):
            if 'vnirange' in parameters:
                return PhysicalNetworkMap.default_key(id_),
            else:
                return ()

        def update_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' in parameters:
                _check_vnirange(parameters['vnirange'])
                try:
                    phymap = walk(PhysicalNetworkMap.default_key(
                        physicalnetwork.id))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    _check_vnirange_allocation(parameters['vnirange'],
                        phymap.network_allocation)
            return default_processor(physicalnetwork, parameters=parameters,
                disabled=('type',))
        return updatephysicalnetwork(update_processor=
            update_physicalnetwork_processor), update_physicalnetwork_keys

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None

    def deletephysicalport(self, type):
        return deletephysicalport(), default_physicalport_keys

    def createlogicalnetwork(self, type):

        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)
                        ] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError('Specified VNI ' + str(vni) +
                        ' allocated or not in range')
            else:
                vni = _findavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError(
                        'no available VNI in physical network ' +
                        physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)
                    ] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork
                .id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'physicalnetwork', 'vni'))
        return createlogicalnetwork(create_processor=
            logicalnetwork_processor, reorder_dict=lambda x: sorted(x.items
            (), key=lambda y: 'vni' in y[1], reverse=True)
            ), default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):

        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return PhysicalNetwork.default_key(id_
                    ), PhysicalNetworkMap.default_key(id_)
            else:
                return ()

        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=
            deallocate_processor)

        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.
                        network_allocation, vni):
                        phymap.network_allocation[str(vni)
                            ] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError('Specified VNI ' + str(vni) +
                            ' allocated or not in range')
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'vni'), disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=
            allocate_processor)

        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):

        def check_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork,
                logicalnetworkmap, physicalnetwork, physicalnetworkmap,
                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor
            ), default_logicalnetwork_keys


def _check_vnirange(vnirange):
    lastend = 0
    for start, end in vnirange:
        if start <= 0 or end > (1 << 24) - 1:
            raise ValueError('VNI out of range (1 - 4095)')
        if start > end or start <= lastend:
            raise ValueError(
                'VNI sequences overlapped or disordered: [%r, %r]' % (start,
                end))
        lastend = end


def _check_vnirange_allocation(vnirange, allocation):
    allocated_ids = sorted(int(k) for k in allocation.keys())
    range_iter = iter(vnirange)
    current_range = None
    for id_ in allocated_ids:
        while current_range is None or current_range[1] < id_:
            try:
                current_range = next(range_iter)
            except StopIteration:
                raise ValueError('Allocated VNI ' + str(id_) +
                    ' not in new VNI range')
        if current_range[0] > id_:
            raise ValueError('Allocated VNI ' + str(id_) +
                ' not in new VNI range')


<mask token>


def _isavaliablevni(vnirange, allocated, vni):
    find = False
    for start, end in vnirange:
        if start <= int(vni) <= end:
            find = True
            break
    if find:
        if str(vni) not in allocated:
            find = True
        else:
            find = False
    else:
        find = False
    return find

<mask token>


@defaultconfig
class NetworkVxlanDriver(Module):
    """
    Network driver for VXLAN networks. When creating a VXLAN type physical network,
    you must specify an extra option ``vnirange``.
    """

    def __init__(self, server):
        super(NetworkVxlanDriver, self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(publicapi(self.createphysicalnetwork, criteria=lambda
            type: type == 'vxlan'), publicapi(self.updatephysicalnetwork,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            deletephysicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.createphysicalport, criteria=lambda type: type ==
            'vxlan'), publicapi(self.updatephysicalport, criteria=lambda
            type: type == 'vxlan'), publicapi(self.deletephysicalport,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            createlogicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.updatelogicalnetwork, criteria=lambda type: type ==
            'vxlan'), publicapi(self.deletelogicalnetwork, criteria=lambda
            type: type == 'vxlan'))

    async def _main(self):
        self._logger.info('network_vxlan_driver running ---')

    def createphysicalnetwork(self, type):

        def create_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError(
                    'must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters,
                excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=
            create_physicalnetwork_processor), default_physicalnetwork_keys

    def updatephysicalnetwork(self, type):

        def update_physicalnetwork_keys(id_, parameters):
            if 'vnirange' in parameters:
                return PhysicalNetworkMap.default_key(id_),
            else:
                return ()

        def update_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' in parameters:
                _check_vnirange(parameters['vnirange'])
                try:
                    phymap = walk(PhysicalNetworkMap.default_key(
                        physicalnetwork.id))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    _check_vnirange_allocation(parameters['vnirange'],
                        phymap.network_allocation)
            return default_processor(physicalnetwork, parameters=parameters,
                disabled=('type',))
        return updatephysicalnetwork(update_processor=
            update_physicalnetwork_processor), update_physicalnetwork_keys

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None

    def deletephysicalport(self, type):
        return deletephysicalport(), default_physicalport_keys

    def createlogicalnetwork(self, type):

        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)
                        ] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError('Specified VNI ' + str(vni) +
                        ' allocated or not in range')
            else:
                vni = _findavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError(
                        'no available VNI in physical network ' +
                        physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)
                    ] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork
                .id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'physicalnetwork', 'vni'))
        return createlogicalnetwork(create_processor=
            logicalnetwork_processor, reorder_dict=lambda x: sorted(x.items
            (), key=lambda y: 'vni' in y[1], reverse=True)
            ), default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):

        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return PhysicalNetwork.default_key(id_
                    ), PhysicalNetworkMap.default_key(id_)
            else:
                return ()

        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=
            deallocate_processor)

        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.
                        network_allocation, vni):
                        phymap.network_allocation[str(vni)
                            ] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError('Specified VNI ' + str(vni) +
                            ' allocated or not in range')
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'vni'), disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=
            allocate_processor)

        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):

        def check_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork,
                logicalnetworkmap, physicalnetwork, physicalnetworkmap,
                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor
            ), default_logicalnetwork_keys


def _check_vnirange(vnirange):
    lastend = 0
    for start, end in vnirange:
        if start <= 0 or end > (1 << 24) - 1:
            raise ValueError('VNI out of range (1 - 4095)')
        if start > end or start <= lastend:
            raise ValueError(
                'VNI sequences overlapped or disordered: [%r, %r]' % (start,
                end))
        lastend = end


def _check_vnirange_allocation(vnirange, allocation):
    allocated_ids = sorted(int(k) for k in allocation.keys())
    range_iter = iter(vnirange)
    current_range = None
    for id_ in allocated_ids:
        while current_range is None or current_range[1] < id_:
            try:
                current_range = next(range_iter)
            except StopIteration:
                raise ValueError('Allocated VNI ' + str(id_) +
                    ' not in new VNI range')
        if current_range[0] > id_:
            raise ValueError('Allocated VNI ' + str(id_) +
                ' not in new VNI range')


def _findavaliablevni(vnirange, allocated):
    vni = None
    for vr in vnirange:
        find = False
        for v in range(vr[0], vr[1] + 1):
            if str(v) not in allocated:
                vni = v
                find = True
                break
        if find:
            break
    return vni


def _isavaliablevni(vnirange, allocated, vni):
    find = False
    for start, end in vnirange:
        if start <= int(vni) <= end:
            find = True
            break
    if find:
        if str(vni) not in allocated:
            find = True
        else:
            find = False
    else:
        find = False
    return find

from vlcp.server.module import Module, publicapi
from vlcp.event.runnable import RoutineContainer
from vlcp.utils.networkmodel import PhysicalNetworkMap, PhysicalNetwork, VXLANEndpointSet
from vlcp.config.config import defaultconfig
from vlcp.utils.networkplugin import createphysicalnetwork, updatephysicalnetwork, default_physicalnetwork_keys, deletephysicalnetwork, deletephysicalport, default_physicalport_keys, createlogicalnetwork, default_logicalnetwork_keys, default_processor, updatelogicalnetwork, deletelogicalnetwork, createphysicalport, updatephysicalport, default_logicalnetwork_delete_check
from vlcp.utils.exceptions import WalkKeyNotRetrieved
from vlcp.utils.walkerlib import ensure_keys


@defaultconfig
class NetworkVxlanDriver(Module):
    """
    Network driver for VXLAN networks. When creating a VXLAN type physical network,
    you must specify an extra option ``vnirange``.
    """

    def __init__(self, server):
        super(NetworkVxlanDriver, self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(publicapi(self.createphysicalnetwork, criteria=lambda
            type: type == 'vxlan'), publicapi(self.updatephysicalnetwork,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            deletephysicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.createphysicalport, criteria=lambda type: type ==
            'vxlan'), publicapi(self.updatephysicalport, criteria=lambda
            type: type == 'vxlan'), publicapi(self.deletephysicalport,
            criteria=lambda type: type == 'vxlan'), publicapi(self.
            createlogicalnetwork, criteria=lambda type: type == 'vxlan'),
            publicapi(self.updatelogicalnetwork, criteria=lambda type: type ==
            'vxlan'), publicapi(self.deletelogicalnetwork, criteria=lambda
            type: type == 'vxlan'))

    async def _main(self):
        self._logger.info('network_vxlan_driver running ---')

    def createphysicalnetwork(self, type):

        def create_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError(
                    'must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters,
                excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=
            create_physicalnetwork_processor), default_physicalnetwork_keys

    def updatephysicalnetwork(self, type):

        def update_physicalnetwork_keys(id_, parameters):
            if 'vnirange' in parameters:
                return PhysicalNetworkMap.default_key(id_),
            else:
                return ()

        def update_physicalnetwork_processor(physicalnetwork, walk, write,
            *, parameters):
            if 'vnirange' in parameters:
                _check_vnirange(parameters['vnirange'])
                try:
                    phymap = walk(PhysicalNetworkMap.default_key(
                        physicalnetwork.id))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    _check_vnirange_allocation(parameters['vnirange'],
                        phymap.network_allocation)
            return default_processor(physicalnetwork, parameters=parameters,
                disabled=('type',))
        return updatephysicalnetwork(update_processor=
            update_physicalnetwork_processor), update_physicalnetwork_keys

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None

    def deletephysicalport(self, type):
        return deletephysicalport(), default_physicalport_keys

    def createlogicalnetwork(self, type):

        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)
                        ] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError('Specified VNI ' + str(vni) +
                        ' allocated or not in range')
            else:
                vni = _findavaliablevni(physicalnetwork.vnirange,
                    physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError(
                        'no available VNI in physical network ' +
                        physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)
                    ] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork
                .id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'physicalnetwork', 'vni'))
        return createlogicalnetwork(create_processor=
            logicalnetwork_processor, reorder_dict=lambda x: sorted(x.items
            (), key=lambda y: 'vni' in y[1], reverse=True)
            ), default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):

        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return PhysicalNetwork.default_key(id_
                    ), PhysicalNetworkMap.default_key(id_)
            else:
                return ()

        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=
            deallocate_processor)

        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(
                        logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.
                        network_allocation, vni):
                        phymap.network_allocation[str(vni)
                            ] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError('Specified VNI ' + str(vni) +
                            ' allocated or not in range')
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters,
                excluding=('id', 'vni'), disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=
            allocate_processor)

        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):

        def check_processor(logicalnetwork, logicalnetworkmap,
            physicalnetwork, physicalnetworkmap, walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork,
                logicalnetworkmap, physicalnetwork, physicalnetworkmap,
                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor
            ), default_logicalnetwork_keys


def _check_vnirange(vnirange):
    lastend = 0
    for start, end in vnirange:
        if start <= 0 or end > (1 << 24) - 1:
            raise ValueError('VNI out of range (1 - 4095)')
        if start > end or start <= lastend:
            raise ValueError(
                'VNI sequences overlapped or disordered: [%r, %r]' % (start,
                end))
        lastend = end


def _check_vnirange_allocation(vnirange, allocation):
    allocated_ids = sorted(int(k) for k in allocation.keys())
    range_iter = iter(vnirange)
    current_range = None
    for id_ in allocated_ids:
        while current_range is None or current_range[1] < id_:
            try:
                current_range = next(range_iter)
            except StopIteration:
                raise ValueError('Allocated VNI ' + str(id_) +
                    ' not in new VNI range')
        if current_range[0] > id_:
            raise ValueError('Allocated VNI ' + str(id_) +
                ' not in new VNI range')


def _findavaliablevni(vnirange, allocated):
    vni = None
    for vr in vnirange:
        find = False
        for v in range(vr[0], vr[1] + 1):
            if str(v) not in allocated:
                vni = v
                find = True
                break
        if find:
            break
    return vni


def _isavaliablevni(vnirange, allocated, vni):
    find = False
    for start, end in vnirange:
        if start <= int(vni) <= end:
            find = True
            break
    if find:
        if str(vni) not in allocated:
            find = True
        else:
            find = False
    else:
        find = False
    return find

from vlcp.server.module import Module, publicapi
from vlcp.event.runnable import RoutineContainer
from vlcp.utils.networkmodel import PhysicalNetworkMap, PhysicalNetwork,\
    VXLANEndpointSet
from vlcp.config.config import defaultconfig
from vlcp.utils.networkplugin import createphysicalnetwork,\
    updatephysicalnetwork, default_physicalnetwork_keys, deletephysicalnetwork,\
    deletephysicalport, default_physicalport_keys, createlogicalnetwork,\
    default_logicalnetwork_keys, default_processor, updatelogicalnetwork,\
    deletelogicalnetwork, createphysicalport, updatephysicalport,\
    default_logicalnetwork_delete_check
from vlcp.utils.exceptions import WalkKeyNotRetrieved
from vlcp.utils.walkerlib import ensure_keys


@defaultconfig
class NetworkVxlanDriver(Module):
    """
    Network driver for VXLAN networks. When creating a VXLAN type physical network,
    you must specify an extra option ``vnirange``.
    """
    def __init__(self,server):
        super(NetworkVxlanDriver,self).__init__(server)
        self.app_routine = RoutineContainer(self.scheduler)
        self.app_routine.main = self._main
        self.routines.append(self.app_routine)
        self.createAPI(
                       publicapi(self.createphysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatephysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletephysicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.createphysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatephysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletephysicalport,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.createlogicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.updatelogicalnetwork,
                                    criteria=lambda type: type == 'vxlan'),
                       publicapi(self.deletelogicalnetwork,
                                    criteria=lambda type: type == "vxlan")
                       )

    async def _main(self):
        self._logger.info("network_vxlan_driver running ---")

    def createphysicalnetwork(self, type):
        # create an new physical network
        def create_physicalnetwork_processor(physicalnetwork, walk, write, *, parameters):
            if 'vnirange' not in parameters:
                raise ValueError('must specify vnirange with physical network type=vxlan')
            _check_vnirange(parameters['vnirange'])
            return default_processor(physicalnetwork, parameters=parameters, excluding=('id', 'type'))
        return createphysicalnetwork(type, create_processor=create_physicalnetwork_processor),\
                default_physicalnetwork_keys

    def updatephysicalnetwork(self, type):
        # update a physical network
        def update_physicalnetwork_keys(id_, parameters):
            if 'vnirange' in parameters:
                return (PhysicalNetworkMap.default_key(id_),)
            else:
                return ()
        def update_physicalnetwork_processor(physicalnetwork, walk, write, *, parameters):
            if 'vnirange' in parameters:
                _check_vnirange(parameters['vnirange'])
                try:
                    phymap = walk(PhysicalNetworkMap.default_key(physicalnetwork.id))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    _check_vnirange_allocation(parameters['vnirange'], phymap.network_allocation)
            return default_processor(physicalnetwork, parameters=parameters, disabled=('type',))
        return updatephysicalnetwork(update_processor=update_physicalnetwork_processor), update_physicalnetwork_keys

    def deletephysicalnetwork(self, type):
        return deletephysicalnetwork(), default_physicalnetwork_keys

    def createphysicalport(self, type):
        return createphysicalport(), default_physicalport_keys

    def updatephysicalport(self, type):
        return updatephysicalport(), None

    def deletephysicalport(self, type):
        return deletephysicalport(), default_physicalport_keys

    def createlogicalnetwork(self, type):
        def logicalnetwork_processor(logicalnetwork, logicalnetworkmap, physicalnetwork,
                                     physicalnetworkmap, walk, write, *, parameters):
            if 'vni' in parameters:
                # Allocate this vni
                vni = int(parameters['vni'])
                if _isavaliablevni(physicalnetwork.vnirange, physicalnetworkmap.network_allocation, vni):
                    physicalnetworkmap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                    write(physicalnetworkmap.getkey(), physicalnetworkmap)
                else:
                    raise ValueError("Specified VNI " + str(vni) + " allocated or not in range")
            else:
                # Allocate a vni from range
                vni = _findavaliablevni(physicalnetwork.vnirange, physicalnetworkmap.network_allocation)
                if vni is None:
                    raise ValueError("no available VNI in physical network " + physicalnetwork.id)
                physicalnetworkmap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                write(physicalnetworkmap.getkey(), physicalnetworkmap)
            logicalnetwork.vni = vni
            write(logicalnetwork.getkey(), logicalnetwork)
            # Create VXLANEndpointSet
            vxlanendpoint_set = VXLANEndpointSet.create_instance(logicalnetwork.id)
            write(vxlanendpoint_set.getkey(), vxlanendpoint_set)
            return default_processor(logicalnetwork, parameters=parameters, excluding=('id', 'physicalnetwork', 'vni'))
        # Process logical networks with specified IDs first
        return createlogicalnetwork(create_processor=logicalnetwork_processor,
                                    reorder_dict=lambda x: sorted(x.items(), key=lambda y: 'vni' in y[1], reverse=True)),\
               default_logicalnetwork_keys

    def updatelogicalnetwork(self, type):
        # When updating VLAN ids, Must first deallocate all VLAN ids, then allocate all
        # Chaining two walkers for this
        def update_logicalnetwork_keys(id_, parameters):
            if 'vni' in parameters:
                return (PhysicalNetwork.default_key(id_),
                        PhysicalNetworkMap.default_key(id_))
            else:
                return ()
        def deallocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phymap = walk(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    pass
                else:
                    del phymap.network_allocation[str(logicalnetwork.vni)]
                    write(phymap.getkey(), phymap)
            return False
        deallocate_walker = updatelogicalnetwork(update_processor=deallocate_processor)
        def allocate_processor(logicalnetwork, walk, write, *, parameters):
            if 'vni' in parameters:
                try:
                    phynet = walk(logicalnetwork.physicalnetwork.getkey())
                    phymap = walk(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                except WalkKeyNotRetrieved:
                    ensure_keys(PhysicalNetworkMap._network.leftkey(logicalnetwork.physicalnetwork))
                else:
                    vni = int(parameters['vni'])
                    if _isavaliablevni(phynet.vnirange, phymap.network_allocation, vni):
                        phymap.network_allocation[str(vni)] = logicalnetwork.create_weakreference()
                        write(phymap.getkey(), phymap)
                    else:
                        raise ValueError("Specified VNI " + str(vni) + " allocated or not in range")
                    logicalnetwork.vni = vni
                    write(logicalnetwork.getkey(), logicalnetwork)
            return default_processor(logicalnetwork, parameters=parameters, excluding=('id', 'vni'),
                                                                            disabled=('physicalnetwork',))
        allocate_walker = updatelogicalnetwork(update_processor=allocate_processor)
        def walker(walk, write, timestamp, parameters_dict):
            deallocate_walker(walk, write, timestamp, parameters_dict)
            allocate_walker(walk, write, timestamp, parameters_dict)
        return walker, update_logicalnetwork_keys

    def deletelogicalnetwork(self, type):
        def check_processor(logicalnetwork, logicalnetworkmap,
                            physicalnetwork, physicalnetworkmap,
                            walk, write, *, parameters):
            default_logicalnetwork_delete_check(logicalnetwork, logicalnetworkmap,
                                                physicalnetwork, physicalnetworkmap,
                                                walk, write, parameters=parameters)
            del physicalnetworkmap.network_allocation[str(logicalnetwork.vni)]
            write(physicalnetworkmap.getkey(), physicalnetworkmap)
        return deletelogicalnetwork(check_processor=check_processor), default_logicalnetwork_keys


def _check_vnirange(vnirange):
    lastend = 0
    for start,end in vnirange:
        if start <= 0 or end > (1 << 24) - 1:
            raise ValueError('VNI out of range (1 - 4095)')
        if start > end or start <= lastend:
            raise ValueError('VNI sequences overlapped or disordered: [%r, %r]' % (start, end))
        lastend = end


def _check_vnirange_allocation(vnirange, allocation):
    allocated_ids = sorted(int(k) for k in allocation.keys())
    range_iter = iter(vnirange)
    current_range = None
    for id_ in allocated_ids:
        while current_range is None or current_range[1] < id_:
            try:
                current_range = next(range_iter)
            except StopIteration:
                raise ValueError("Allocated VNI " + str(id_) + " not in new VNI range")
        if current_range[0] > id_:
            raise ValueError("Allocated VNI " + str(id_) + " not in new VNI range")


def _findavaliablevni(vnirange,allocated):
    
    vni = None
    for vr in vnirange:
        find = False
        for v in range(vr[0],vr[1] + 1):
            if str(v) not in allocated:
                vni = v
                find = True
                break

        if find:
            break
    return vni


def _isavaliablevni(vnirange,allocated,vni):
    
    find = False
    for start,end in vnirange:
        if start <= int(vni) <= end:
            find = True
            break

    if find:
        if str(vni) not in allocated:
            find = True
        else:
            find = False
    else:
        find = False

    return find
