コード例 #1
0
    def assign_ip(self, address, handle_id, attributes, hostname=None):
        """
        Assign the given address.  Throws AlreadyAssignedError if the address
        is taken.

        :param address: IPAddress to assign.
        :param handle_id: allocation handle ID for this request.  You can
        query this key using get_assignments_by_handle() or release all
        addresses with this handle_id using release_by_handle().
        :param attributes: Contents of this dict will be stored with the
        assignment and can be queried using get_assignment_attributes().  Must
        be JSON serializable.
        :param hostname: (optional) the hostname to use for affinity if the
        block containing the IP address has no host affinity.  Defaults to the
        hostname returned by get_hostname().
        :return: None.
        """
        assert isinstance(handle_id, str) or handle_id is None
        assert isinstance(address, IPAddress)
        if not hostname:
            hostname = get_hostname()
        block_cidr = get_block_cidr_for_address(address)

        for _ in xrange(RETRIES):
            try:
                block = self._read_block(block_cidr)
            except KeyError:
                _log.debug("Block %s doesn't exist.", block_cidr)
                pools = self.get_ip_pools(address.version, ipam=True)
                if any([address in pool for pool in pools]):
                    _log.debug("Create and claim block %s.", block_cidr)
                    try:
                        self._claim_block_affinity(hostname, block_cidr)
                    except HostAffinityClaimedError:
                        _log.debug("Someone else claimed block %s before us.",
                                   block_cidr)
                        continue
                    # Block exists now, retry writing to it.
                    _log.debug("Claimed block %s", block_cidr)
                    continue
                else:
                    raise ValueError("%s is not in any configured pool" %
                                     address)

            # Try to assign.  Throws exception if already assigned -- let it.
            block.assign(address, handle_id, attributes)

            # If using a handle, increment by one IP
            if handle_id is not None:
                self._increment_handle(handle_id, block_cidr, 1)

            # Try to commit.
            try:
                self._compare_and_swap_block(block)
                return  # Success!
            except CASError:
                _log.debug("CAS failed on block %s", block_cidr)
                if handle_id is not None:
                    self._decrement_handle(handle_id, block_cidr, 1)
        raise RuntimeError("Hit max retries.")
コード例 #2
0
ファイル: ipam.py プロジェクト: djosborne/libcalico
    def get_assignment_attributes(self, address):
        """
        Return the attributes of a given address.

        :param address: IPAddress to query.
        :return: The attributes for the address as passed to auto_assign() or
        assign().
        """
        assert isinstance(address, IPAddress)
        block_cidr = get_block_cidr_for_address(address)

        try:
            block = self._read_block(block_cidr)
        except KeyError:
            _log.warning("Couldn't read block %s for requested address %s",
                         block_cidr, address)
            raise AddressNotAssignedError("%s is not assigned." % address)
        else:
            _, attributes = block.get_attributes_for_ip(address)
            return attributes
コード例 #3
0
ファイル: ipam.py プロジェクト: cheuschober/libcalico
    def get_assignment_attributes(self, address):
        """
        Return the attributes of a given address.

        :param address: IPAddress to query.
        :return: The attributes for the address as passed to auto_assign() or
        assign().
        """
        assert isinstance(address, IPAddress)
        block_cidr = get_block_cidr_for_address(address)

        try:
            block = self._read_block(block_cidr)
        except KeyError:
            _log.warning("Couldn't read block %s for requested address %s",
                         block_cidr, address)
            raise AddressNotAssignedError("%s is not assigned." % address)
        else:
            _, attributes = block.get_attributes_for_ip(address)
            return attributes
コード例 #4
0
ファイル: ipam.py プロジェクト: djosborne/libcalico
    def release_ips(self, addresses):
        """
        Release the given addresses.

        :param addresses: Set of IPAddresses to release (ok to mix IPv4 and
        IPv6).
        :return: Set of addresses that were already unallocated.
        """
        assert isinstance(addresses, (set, frozenset))
        _log.info("Releasing addresses %s", [str(addr) for addr in addresses])
        unallocated = set()
        # sort the addresses into blocks
        addrs_by_block = {}
        for address in addresses:
            block_cidr = get_block_cidr_for_address(address)
            addrs = addrs_by_block.setdefault(block_cidr, set())
            addrs.add(address)

        # loop through blocks, CAS releasing.
        for block_cidr, addresses in addrs_by_block.iteritems():
            unalloc_block = self._release_block(block_cidr, addresses)
            unallocated = unallocated.union(unalloc_block)
        return unallocated
コード例 #5
0
ファイル: ipam.py プロジェクト: cheuschober/libcalico
    def release_ips(self, addresses):
        """
        Release the given addresses.

        :param addresses: Set of IPAddresses to release (ok to mix IPv4 and
        IPv6).
        :return: Set of addresses that were already unallocated.
        """
        assert isinstance(addresses, (set, frozenset))
        _log.info("Releasing addresses %s", [str(addr) for addr in addresses])
        unallocated = set()
        # sort the addresses into blocks
        addrs_by_block = {}
        for address in addresses:
            block_cidr = get_block_cidr_for_address(address)
            addrs = addrs_by_block.setdefault(block_cidr, set())
            addrs.add(address)

        # loop through blocks, CAS releasing.
        for block_cidr, addresses in addrs_by_block.iteritems():
            unalloc_block = self._release_block(block_cidr, addresses)
            unallocated = unallocated.union(unalloc_block)
        return unallocated
コード例 #6
0
 def test_get_block_cidr(self, address, cidr):
     """
     Test get_block_cidr_for_address
     """
     block_id = get_block_cidr_for_address(address)
     assert_equal(block_id, cidr)
コード例 #7
0
ファイル: block_test.py プロジェクト: fasaxc/libcalico
 def test_get_block_cidr(self, address, cidr):
     """
     Test get_block_cidr_for_address
     """
     block_id = get_block_cidr_for_address(address)
     assert_equal(block_id, cidr)
コード例 #8
0
ファイル: ipam.py プロジェクト: djosborne/libcalico
    def assign_ip(self, address, handle_id, attributes, host=None):
        """
        Assign the given address.  Throws AlreadyAssignedError if the address
        is taken.

        :param address: IPAddress to assign.
        :param handle_id: allocation handle ID for this request.  You can
        query this key using get_assignments_by_handle() or release all
        addresses with this handle_id using release_by_handle().
        :param attributes: Contents of this dict will be stored with the
        assignment and can be queried using get_assignment_attributes().  Must
        be JSON serializable.
        :param host: (optional) The host ID to use for affinity in assigning IP
        addresses.  Defaults to the hostname returned by get_hostname().
        :return: None.
        """
        assert isinstance(handle_id, str) or handle_id is None
        assert isinstance(address, IPAddress)
        if not host:
            host = get_hostname()
        block_cidr = get_block_cidr_for_address(address)

        for _ in xrange(RETRIES):
            try:
                block = self._read_block(block_cidr)
            except KeyError:
                _log.debug("Block %s doesn't exist.", block_cidr)
                pools = self.get_ip_pools(address.version, ipam=True)
                if any([address in pool for pool in pools]):
                    _log.debug("Create and claim block %s.",
                               block_cidr)
                    try:
                        self._claim_block_affinity(host, block_cidr)
                    except HostAffinityClaimedError:
                        _log.debug("Someone else claimed block %s before us.",
                                   block_cidr)
                        continue
                    # Block exists now, retry writing to it.
                    _log.debug("Claimed block %s", block_cidr)
                    continue
                else:
                    raise PoolNotFound("%s is not in any configured pool" %
                                       address)

            # Try to assign.  Throws exception if already assigned -- let it.
            block.assign(address, handle_id, attributes)

            # If using a handle, increment by one IP
            if handle_id is not None:
                self._increment_handle(handle_id, block_cidr, 1)

            # Try to commit.
            try:
                self._compare_and_swap_block(block)
                return  # Success!
            except CASError:
                _log.debug("CAS failed on block %s", block_cidr)
                if handle_id is not None:
                    self._decrement_handle(handle_id,
                                           block_cidr,
                                           1)
        raise RuntimeError("Hit max retries.")