Ejemplo n.º 1
0
 def __contains__(self, item):
     item = IPAddr(item)
     if item in self.removed: return False
     n = item.toUnsigned()
     mask = (1 << self.host_size) - 1
     nm = (n & mask) | self.network.toUnsigned()
     if nm != n: return False
     if (n & mask) == mask:
         return False
     if (n & mask) < self.first:
         return False
     if (n & mask) > self.last:
         return False
     return True
Ejemplo n.º 2
0
class SimpleAddressPool(AddressPool):
    """
    Simple AddressPool for simple subnet based pools.
    """

    def __init__(self, network="192.168.0.0/24", first=1, last=None,
                 count=None):
        """
        Simple subnet-based address pool

        Allocates count IP addresses out of network/network_size, starting
        with the first'th.  You may specify the end of the range with either
        last (to specify the last'th address to use) or count to specify the
        number to use.  If both are None, use up to the end of all
        legal addresses.

        Example for all of 192.168.x.x/16:
          SimpleAddressPool("192.168.0.0/16", 1, 65534)
        """
        network, network_size = parse_cidr(network)

        self.first = first
        self.network_size = network_size
        self.host_size = 32 - network_size
        self.network = IPAddr(network)

        if last is None and count is None:
            self.last = (1 << self.host_size) - 2
        elif last is not None:
            self.last = last
        elif count is not None:
            self.last = self.first + count - 1
        else:
            raise RuntimeError("Cannot specify both last and count")

        self.removed = set()

        if self.count <= 0: raise RuntimeError("Bad first/last range")
        if first == 0: raise RuntimeError("Can't allocate 0th address")
        if self.host_size < 0 or self.host_size > 32:
            raise RuntimeError("Bad network")
        if IPAddr(self.last | self.network.toUnsigned()) not in self:
            raise RuntimeError("Bad first/last range")

    def __repr__(self):
        return str(self)

    def __str__(self):
        t = self.network.toUnsigned()
        t = (IPAddr(t | self.first), IPAddr(t | self.last))
        return "<Addresses from %s to %s>" % t

    @property
    def subnet_mask(self):
        return IPAddr(((1 << self.network_size) - 1) << self.host_size)

    @property
    def count(self):
        return self.last - self.first + 1

    def __contains__(self, item):
        item = IPAddr(item)
        if item in self.removed: return False
        n = item.toUnsigned()
        mask = (1 << self.host_size) - 1
        nm = (n & mask) | self.network.toUnsigned()
        if nm != n: return False
        if (n & mask) == mask:
            return False
        if (n & mask) < self.first:
            return False
        if (n & mask) > self.last:
            return False
        return True

    def append(self, item):
        item = IPAddr(item)
        if item not in self.removed:
            if item in self:
                raise RuntimeError("%s is already in this pool" % (item,))
            else:
                raise RuntimeError("%s does not belong in this pool" % (item,))
        self.removed.remove(item)

    def remove(self, item):
        item = IPAddr(item)
        if item not in self:
            raise RuntimeError("%s not in this pool" % (item,))
        self.removed.add(item)

    def __len__(self):
        return (self.last - self.first + 1) - len(self.removed)

    def __getitem__(self, index):
        if index < 0:
            raise RuntimeError("Negative indices not allowed")
        if index >= len(self):
            raise IndexError("Item does not exist")
        c = self.first

        # Use a heuristic to find the first element faster (we hope)
        # Note this means that removing items changes the order of
        # our "list".
        c += len(self.removed)
        while c > self.last:
            c -= self.count

        while True:
            addr = IPAddr(c | self.network.toUnsigned())
            if addr not in self.removed:
                assert addr in self
            index -= 1
            if index < 0:
                return addr
            c += 1
            if c > self.last:
                c -= self.count