def count_in_range(self, start, stop): return self.query_1(""" SELECT count(ipv6_number_id) FROM [:table schema=cerebrum name=dns_ipv6_number] WHERE aaaa_ip >= :start AND aaaa_ip <= :stop""", { 'start': IPv6Utils.explode(IPv6Calc.long_to_ip(start)), 'stop': IPv6Utils.explode(IPv6Calc.long_to_ip(stop))})
def aaaa_cmp(x,y): if IPv6Calc.ip_to_long(self.aaaa_records[x]['aaaa_ip']) == \ IPv6Calc.ip_to_long(self.aaaa_records[y]['aaaa_ip']): return 0 elif IPv6Calc.ip_to_long(self.aaaa_records[x]['aaaa_ip']) < \ IPv6Calc.ip_to_long(self.aaaa_records[y]['aaaa_ip']): return -1 else: return 1
def count_in_range(self, start, stop): return self.query_1( """ SELECT count(ipv6_number_id) FROM [:table schema=cerebrum name=dns_ipv6_number] WHERE aaaa_ip >= :start AND aaaa_ip <= :stop""", { 'start': IPv6Utils.explode(IPv6Calc.long_to_ip(start)), 'stop': IPv6Utils.explode(IPv6Calc.long_to_ip(stop)) })
def aaaa_cmp(x, y): if IPv6Calc.ip_to_long(self.aaaa_records[x]['aaaa_ip']) == \ IPv6Calc.ip_to_long(self.aaaa_records[y]['aaaa_ip']): return 0 elif IPv6Calc.ip_to_long(self.aaaa_records[x]['aaaa_ip']) < \ IPv6Calc.ip_to_long(self.aaaa_records[y]['aaaa_ip']): return -1 else: return 1
def populate(self, subnet, description, vlan=None): """Populate subnet instance's attributes.""" Entity.populate(self, self.const.entity_dns_ipv6_subnet) # If __in_db is present, it must be True; calling populate on # an object where __in_db is present and False is very likely # a programming error. # # If __in_db in not present, we'll set it to False. try: if not self.__in_db: raise RuntimeError("populate() called multiple times.") except AttributeError: self.__in_db = False self.subnet_ip, subnet_mask = subnet.split('/') self.subnet_mask = int(subnet_mask) self.subnet_ip = IPv6Utils.explode(self.subnet_ip) self.ip_min, self.ip_max = IPv6Calc.ip_range_by_netmask( self.subnet_ip, self.subnet_mask) self.description = description self.vlan = vlan self.name_prefix = '' # TODO: Fix this res_net_size = cereconf.DEFAULT_RESERVED_BY_IPv6_NET_SIZE max_res = max(res_net_size.values()) self.no_of_reserved_adr = res_net_size.get(self.subnet_mask, max_res) self.calculate_reserved_addresses()
def populate(self, subnet, description, vlan=None): """Populate subnet instance's attributes.""" Entity.populate(self, self.const.entity_dns_ipv6_subnet) # If __in_db is present, it must be True; calling populate on # an object where __in_db is present and False is very likely # a programming error. # # If __in_db in not present, we'll set it to False. try: if not self.__in_db: raise RuntimeError("populate() called multiple times.") except AttributeError: self.__in_db = False self.subnet_ip, subnet_mask = subnet.split('/') self.subnet_mask = int(subnet_mask) self.subnet_ip = IPv6Utils.explode(self.subnet_ip) self.ip_min, self.ip_max = IPv6Calc.ip_range_by_netmask( self.subnet_ip, self.subnet_mask) self.description = description self.vlan = vlan # TODO: Fix this max_res = max(cereconf.DEFAULT_RESERVED_BY_IPv6_NET_SIZE.values()) self.no_of_reserved_adr = cereconf.DEFAULT_RESERVED_BY_IPv6_NET_SIZE.get( self.subnet_mask, max_res) self.calculate_reserved_addresses()
def _find_available_ip(self, subnet, no_of_addrs=None, search_start=0): """Returns all ips that are not reserved or taken on the given subnet in ascending order.""" try: sub = Subnet.Subnet(self._db) sub.find(subnet) ip_number = IPNumber.IPNumber(self._db) ip_key = 'ip_number_id' ipnr = lambda x: x['ipnr'] start = sub.ip_min except SubnetError: sub = IPv6Subnet.IPv6Subnet(self._db) sub.find(subnet) ip_number = IPv6Number.IPv6Number(self._db) ip_key = 'ipv6_number_id' ipnr = lambda x: IPv6Calc.ip_to_long(x['aaaa_ip']) # We'll do this, since we don't want bofh to be stuck forever # trying to fetch all IPv6-addresses. # This is ugly, but it's not only-only. if no_of_addrs is None: no_of_addrs = 100 # A special case for IPv6 subnets, is that we'll want to be able # to start allocating addresses a given place in the subnet, # without using the reserved-addresses-functionality. if search_start >= sub.ip_min: start = search_start else: start = (sub.ip_min + cereconf.DEFAULT_IPv6_SUBNET_ALLOCATION_START + search_start) try: taken = {} for row in ip_number.find_in_range(start, sub.ip_max): taken[long(ipnr(row))] = int(row[ip_key]) stop = sub.ip_max - start + 1 n = 0 ret = [] while n < stop: if no_of_addrs is not None and len(ret) == no_of_addrs: break if ( long(start+n) not in taken and n+start not in sub.reserved_adr ): ret.append(n+start) n += 1 return ret except SubnetError: # Unable to find subnet; therefore, no available ips to report return []
def check_reserved_addresses_in_use(self): """Raise a SubnetError if this subnet has addresses in use, that are really reserved. """ ip_number = IPv6Number.IPv6Number(self._db) ip_number.clear() res_adr_in_use = [] for row in ip_number.find_in_range(self.ip_min, self.ip_max): current_address = IPv6Calc.ip_to_long(row['aaaa_ip']) if current_address in self.reserved_adr: res_adr_in_use.append(row['aaaa_ip']) if res_adr_in_use: res_adr_in_use.sort() raise SubnetError("The following reserved ip's are already in " + "use on (new?) subnet %s/%s: " % (self.subnet_ip, self.subnet_mask) + "'%s'." % (', '.join(res_adr_in_use)))
def check_reserved_addresses_in_use(self): """Raise a SubnetError if this subnet has addresses in use, that are really reserved. """ ip_number = IPv6Number.IPv6Number(self._db) ip_number.clear() res_adr_in_use = [] for row in ip_number.find_in_range(self.ip_min, self.ip_max): current_address = IPv6Calc.ip_to_long(row['aaaa_ip']) if current_address in self.reserved_adr: res_adr_in_use.append(row['aaaa_ip']) if res_adr_in_use: res_adr_in_use.sort() raise SubnetError( "The following reserved ip's are already in " + "use on (new?) subnet %s/%s: " % (self.subnet_ip, self.subnet_mask) + "'%s'." % (', '.join(res_adr_in_use)))
def aaaa_key(x): return IPv6Calc.ip_to_long(self.aaaa_records[x]['aaaa_ip'])
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. '2002:123:111::/64'. - A string with an IPv6 address, e.g. '2001:700:111::0:12'. """ binds = {} if identifier is None: raise SubnetError("Unable to find IPv6 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] binds['subnet_ip'] = IPv6Utils.explode(subnet_ip) else: # Last valid type is simply an IP; need to find correct range where_param = "ip_min <= :ip AND ip_max >= :ip" binds['ip'] = IPv6Calc.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_ipv6_subnet] WHERE %s""" % where_param, binds) self.__super.find(eid) self.subnet_mask = IPv6Subnet.calculate_subnet_mask( self.ip_min, self.ip_max) self.calculate_reserved_addresses() except NotFoundError: raise SubnetError("Unable to find IPv6 subnet identified" " by '%s'" % identifier) self.__in_db = True self.__updated = []
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. '2002:123:111::/64'. - A string with an IPv6 address, e.g. '2001:700:111::0:12'. """ binds = {} if identifier is None: raise SubnetError("Unable to find IPv6 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] binds['subnet_ip'] = IPv6Utils.explode(subnet_ip) else: # Last valid type is simply an IP; need to find correct range where_param = "ip_min <= :ip AND ip_max >= :ip" binds['ip'] = IPv6Calc.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_ipv6_subnet] WHERE %s""" % where_param, binds) self.__super.find(eid) self.subnet_mask = IPv6Subnet.calculate_subnet_mask(self.ip_min, self.ip_max) self.calculate_reserved_addresses() except NotFoundError: raise SubnetError("Unable to find IPv6 subnet identified by '%s'" % identifier) self.__in_db = True self.__updated = []