def parse_subnet_or_ip(self, ip_id): """Parse ip_id either as a subnet, or as an IP-number. Return: (subnet, ip) - subnet is None if unknown - ip is only set if the user requested a specific IP A request for a subnet is identified by a trailing /, or for IPv4 an IP with < 4 octets. IPv6-subnets must always be specified with a trailing /, followed by a mask number. Examples:: 129.240.200 -> adress on 129.240.200.0/23 129.240.200.0/ -> adress on 129.240.200.0/23 129.240.200.0 -> explicit IP 2001:700:100:2::/64 -> address on 2001:700:100:2::/64 2001:700:100:2::3 -> explicit IP """ tmp = ip_id.split("/") ip = tmp[0] subnet_slash = len(tmp) > 1 full_ip = False if IPUtils.is_valid_ipv4(ip): # ipv4 IPUtils.parse_ipv4(ip) if ip.count('.') == 3 and not subnet_slash: full_ip = True elif ip.count('.') == 3 and subnet_slash or \ ip.count('.') == 2 and not subnet_slash: pass else: raise CerebrumError(("'%s' does not look like a valid subnet " "or ip-address.") % ip_id) elif IPv6Utils.is_valid_ipv6(ip_id): # full ipv6 full_ip = True ip = ip_id elif IPv6Subnet.IPv6Subnet.is_valid_subnet(ip_id): ip = ip_id else: try: # Assume hostname self._arecord.clear() self._arecord.find_by_name(self.qualify_hostname(ip)) self._ip_number.clear() self._ip_number.find(self._arecord.ip_number_id) except Errors.NotFoundError: raise CerebrumError("Could not find host %s" % ip) ip = self._ip_number.a_ip try: ipc = Find(self._db, None) subnet_ip = ipc._find_subnet(ip) except: subnet_ip = None return subnet_ip, full_ip and ip or None
def parse_subnet_or_ip(self, ip_id): """Parse ip_id either as a subnet, or as an IP-number. Return: (subnet, ip) - subnet is None if unknown - ip is only set if the user requested a specific IP A request for a subnet is identified by a trailing /, or for IPv4 an IP with < 4 octets. IPv6-subnets must always be specified with a trailing /, followed by a mask number. Examples:: 129.240.200 -> adress on 129.240.200.0/23 129.240.200.0/ -> adress on 129.240.200.0/23 129.240.200.0 -> explicit IP 2001:700:100:2::/64 -> address on 2001:700:100:2::/64 2001:700:100:2::3 -> explicit IP """ tmp = ip_id.split("/") ip = tmp[0] subnet_slash = len(tmp) > 1 full_ip = False if IPUtils.is_valid_ipv4(ip): # ipv4 IPUtils.parse_ipv4(ip) if ip.count('.') == 3 and not subnet_slash: full_ip = True elif ip.count('.') == 3 and subnet_slash or \ ip.count('.') == 2 and not subnet_slash: pass else: raise CerebrumError(("'%s' does not look like a valid subnet " "or ip-address.") % ip_id) elif IPv6Utils.is_valid_ipv6(ip_id): # full ipv6 full_ip = True ip = ip_id elif IPv6Subnet.IPv6Subnet.is_valid_subnet(ip_id): ip = ip_id else: try: # Assume hostname self._arecord.clear() self._arecord.find_by_name(self.qualify_hostname(ip)) self._ip_number.clear() self._ip_number.find(self._arecord.ip_number_id) except Errors.NotFoundError: raise CerebrumError("Could not find host %s" % ip) ip = self._ip_number.a_ip try: ipc = Find(self._db, None) subnet_ip = ipc._find_subnet(ip) except: subnet_ip = None return subnet_ip, full_ip and ip or None
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 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 validate_subnet(subnet): """Validates that a subnet specification is correctly formatted and with legal values. Raises SubnetError if invalid. """ try: ip, mask = subnet.split('/') mask = int(mask) except ValueError: raise SubnetError("Not a valid subnet '%s'" % subnet) if not IPv6Utils.is_valid_ipv6(ip): raise SubnetError("Invalid adress: %s" % ip) # TODO 25-08-2015: # Since Subnet-masks for IPv6 are not properly implemented yet, this # will validate an unspecified subnet mask (''), enabling bofh-users # to specify a subnet like this: '2007:700:111:1/'. This should be # fixed when/if proper subnet-handling is implemented. if mask < 0 or mask > 128: raise SubnetError("Invalid subnet mask '%s'; " "outside range 0-128" % mask) return True
def validate_subnet(subnet): """Validates that a subnet specification is correctly formatted and with legal values. Raises SubnetError if invalid. """ try: ip, mask = subnet.split('/') mask = int(mask) except ValueError: raise SubnetError("Not a valid subnet '%s'" % subnet) if not IPv6Utils.is_valid_ipv6(ip): raise SubnetError("Invalid adress: %s" % ip) # TODO 25-08-2015: # Since Subnet-masks for IPv6 are not properly implemented yet, this # will validate an unspecified subnet mask (''), enabling bofh-users # to specify a subnet like this: '2007:700:111:1/'. This should be # fixed when/if proper subnet-handling is implemented. if mask < 0 or mask > 128: raise SubnetError("Invalid subnet mask '%s'; " "outside range 0-128" % mask) return True
def test_not_is_valid_ipv6(addr): assert not IPv6Utils.is_valid_ipv6(addr)