def migrate_static_ranges_to_admin_reserved(apps, schema_editor): Subnet = apps.get_model("maasserver", "Subnet") IPRange = apps.get_model("maasserver", "IPRange") for subnet in Subnet.objects.all(): static_range = subnet.iprange_set.filter( type=IPRANGE_TYPE.MANAGED_STATIC).first() if static_range is None: continue created_time = static_range.created reserved_ranges = [ make_iprange(iprange.start_ip, iprange.end_ip, iprange.type) for iprange in subnet.iprange_set.filter(type__in=[ IPRANGE_TYPE.MANAGED_STATIC, IPRANGE_TYPE.DYNAMIC, IPRANGE_TYPE.MANAGED_DHCP, IPRANGE_TYPE.UNMANAGED_DHCP, ]) ] convert_static_ipranges_to_reserved( IPRange, subnet, reserved_ranges, created_time, "%s-%s" % (static_range.start_ip, static_range.end_ip), ) subnet.iprange_set.filter(type=IPRANGE_TYPE.MANAGED_STATIC).delete()
def get_maasipset_for_neighbours(self) -> MAASIPSet: """Return the observed neighbours in this subnet. :return: MAASIPSet of neighbours (with the "neighbour" purpose). """ # Circular imports. from maasserver.models import Discovery # Note: we only need unknown IP addresses here, because the known # IP addresses should already be covered by get_ipranges_in_use(). neighbours = Discovery.objects.filter(subnet=self).by_unknown_ip() neighbour_set = { make_iprange(neighbour.ip, purpose="neighbour") for neighbour in neighbours } return MAASIPSet(neighbour_set)
def _get_ranges_for_allocated_ips(self, ipnetwork: IPNetwork, ignore_discovered_ips: bool) -> set: """Returns a set of MAASIPRange objects created from the set of allocated StaticIPAddress objects. """ # Note, the original implementation used .exclude() to filter, # but we'll filter at runtime so that prefetch_related in the # websocket works properly. ranges = set() for sip in self.staticipaddress_set.all(): if sip.ip and not (ignore_discovered_ips and (sip.alloc_type == IPADDRESS_TYPE.DISCOVERED)): ip = IPAddress(sip.ip) if ip in ipnetwork: ranges.add(make_iprange(ip, purpose="assigned-ip")) return ranges
def _get_ranges_for_allocated_ips(self, ipnetwork: IPNetwork, ignore_discovered_ips: bool) -> set: """Returns a set of MAASIPRange objects created from the set of allocated StaticIPAddress objects. """ ranges = set() # We work with tuple rather than real model objects, since a # subnet may many IPs and creating a model object for each IP is # slow. ips = self.get_allocated_ips() for ip, alloc_type in ips: if ip and not (ignore_discovered_ips and (alloc_type == IPADDRESS_TYPE.DISCOVERED)): ip = IPAddress(ip) if ip in ipnetwork: ranges.add(make_iprange(ip, purpose="assigned-ip")) return ranges
def get_ipranges_in_use( self, exclude_addresses: IPAddressExcludeList = None, ranges_only: bool = False, include_reserved: bool = True, with_neighbours: bool = False, ignore_discovered_ips: bool = False, exclude_ip_ranges: list = None, cached_staticroutes: list = None, ) -> MAASIPSet: """Returns a `MAASIPSet` of `MAASIPRange` objects which are currently in use on this `Subnet`. :param exclude_addresses: Additional addresses to consider "in use". :param ignore_discovered_ips: DISCOVERED addresses are not "in use". :param ranges_only: if True, filters out gateway IPs, static routes, DNS servers, and `exclude_addresses`. :param with_neighbours: If True, includes addresses learned from neighbour observation. """ if exclude_addresses is None: exclude_addresses = [] ranges = set() network = self.get_ipnetwork() if network.version == 6: # For most IPv6 networks, automatically reserve the range: # ::1 - ::ffff:ffff # We expect the administrator will be using ::1 through ::ffff. # We plan to reserve ::1:0 through ::ffff:ffff for use by MAAS, # so that we can allocate addresses in the form: # ::<node>:<child> # For now, just make sure IPv6 addresses are allocated from # *outside* both ranges, so that they won't conflict with addresses # reserved from this scheme in the future. first = str(IPAddress(network.first)) first_plus_one = str(IPAddress(network.first + 1)) second = str(IPAddress(network.first + 0xFFFFFFFF)) if network.prefixlen == 64: ranges |= { make_iprange(first_plus_one, second, purpose="reserved") } # Reserve the subnet router anycast address, except for /127 and # /128 networks. (See RFC 6164, and RFC 4291 section 2.6.1.) if network.prefixlen < 127: ranges |= { make_iprange(first, first, purpose="rfc-4291-2.6.1") } if not ranges_only: if (self.gateway_ip is not None and self.gateway_ip != "" and self.gateway_ip in network): ranges |= {make_iprange(self.gateway_ip, purpose="gateway-ip")} if self.dns_servers is not None: ranges |= set( make_iprange(server, purpose="dns-server") for server in self.dns_servers if server in network) if cached_staticroutes is not None: static_routes = [ static_route for static_route in cached_staticroutes if static_route.source == self ] else: static_routes = StaticRoute.objects.filter(source=self) for static_route in static_routes: ranges |= { make_iprange(static_route.gateway_ip, purpose="gateway-ip") } ranges |= self._get_ranges_for_allocated_ips( network, ignore_discovered_ips) ranges |= set( make_iprange(address, purpose="excluded") for address in exclude_addresses if address in network) if include_reserved: ranges |= self.get_reserved_maasipset( exclude_ip_ranges=exclude_ip_ranges) ranges |= self.get_dynamic_maasipset( exclude_ip_ranges=exclude_ip_ranges) if with_neighbours: ranges |= self.get_maasipset_for_neighbours() return MAASIPSet(ranges)
def get_MAASIPRange(self): purpose = self.type # Using '-' instead of '_' is just for consistency. # APIs in previous MAAS releases used '-' in range types. purpose = purpose.replace("_", "-") return make_iprange(self.start_ip, self.end_ip, purpose=purpose)