def get_relevant_ips(self, subnet_or_ip, force=False, no_of_addrs=None): """ Returns a list of available IPs. If a subnet is given as input, the list consists of avaiable IPs on the subnet. If a specific IP is given as input, the list will only contain that IP. :param subnet_or_ip: An IPv4/IPv6 subnet or IP-address :type subnet_or_ip: str :param force: Indicates if the method should attempt to force the operation, even if there is no record that the IP given as input belongs to any subnet records. :type force: boolean :param no_of_addrs: The max number of ips to be returned. :type no_of_addrs: int :returns: A list of available IPs found, or a list containing only the specified IP given to the method in subnet_or_ip, if it is evaluated to a full IP. :rtype: list """ subnet, ip = self._parser.parse_subnet_or_ip(subnet_or_ip) if subnet is None and not force: raise CerebrumError("Unknown subnet. Must force") elif subnet is None and ip is None: raise CerebrumError("Please specify a valid subnet or IP-address.") elif subnet is not None and ip is None: first = subnet_or_ip.split('/')[0] if IPUtils.is_valid_ipv4(first): first = IPCalc.ip_to_long(first) elif IPv6Utils.is_valid_ipv6(first): first = None free_ip_numbers = self._find.find_free_ip(subnet, first=first, no_of_addrs=no_of_addrs) else: free_ip_numbers = [ip] return free_ip_numbers
def find(self, identifier): """Find and instantiate the subnet entity with data from the db. @type identifier: mixed @param identifier: The identifier of the Subnet. Note that the DNS module behaves a bit differently than other Cerebrum modules, in that this find method accepts other input than entity_id. Possibilities are: - A string containing the entity_id, prefixed with 'entity_id:' or 'id:'. - A string with a subnet address, e.g. '10.0.1.0/16'. - A string with an IP address, e.g. '10.0.1.57'. """ binds = {} if identifier is None: raise SubnetError("Unable to find IPv4 subnet identified by '%s'" % identifier) if isinstance(identifier, (str, unicode)) and identifier.count(':') >= 2: # This is probably an IPv6 subnet raise SubnetError("Unable to find IPv4 subnet identified by '%s'" % identifier) if isinstance(identifier, (int, long)): # The proper way of running find() where_param = "entity_id = :e_id" binds['e_id'] = identifier elif identifier.startswith('id:') or identifier.startswith('entity_id:'): # E.g. 'id:X' or 'entity_id:X'; where_param = "entity_id = :e_id" try: binds['e_id'] = int(identifier.split(':')[1]) except ValueError: raise SubnetError("Entity ID must be an integer") elif identifier.find('/') > 0: # A '/' indicates a subnet spec: just need the ip where_param = "subnet_ip = :subnet_ip" subnet_ip = identifier.split('/')[0] if len(subnet_ip.split(".")) == 3: subnet_ip += ".0" binds['subnet_ip'] = subnet_ip else: # Last valid type is simply an IP; need to find correct range if len(identifier.split(".")) == 3: identifier += ".0" where_param = "ip_min <= :ip AND ip_max >= :ip" binds['ip'] = IPCalc.ip_to_long(identifier) try: (eid, self.subnet_ip, self.ip_min, self.ip_max, self.description, self.dns_delegated, self.name_prefix, self.vlan_number, self.no_of_reserved_adr) = self.query_1( """SELECT entity_id, subnet_ip, ip_min, ip_max, description, dns_delegated, name_prefix, vlan_number, no_of_reserved_adr FROM [:table schema=cerebrum name=dns_subnet] WHERE %s""" % where_param, binds) self.__super.find(eid) self.subnet_mask = Subnet.calculate_subnet_mask(self.ip_min, self.ip_max) self.calculate_reserved_addresses() except NotFoundError: raise SubnetError("Unable to find IPv4 subnet identified by '%s'" % identifier) self.__in_db = True self.__updated = []