Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
    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)
Ejemplo n.º 6
0
 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)