def get_vrf_prefix(self, request, vrf_id, afi, prefix): vrf = self.get_object_or_404(VRF, id=int(vrf_id)) if not prefix: prefix = VRF.IPv4_ROOT if afi == "4" else VRF.IPv6_ROOT if (afi == "4" and (not is_ipv4_prefix(prefix) or not vrf.afi_ipv4)) or ( afi == "6" and (not is_ipv6_prefix(prefix) or not vrf.afi_ipv6) ): return self.response_forbidden("Invalid prefix") prefix = self.get_object_or_404(Prefix, vrf=vrf, afi=afi, prefix=prefix) return self.prefix_contents(request, prefix=prefix)
def view_vrf_index(self, request, vrf_id, afi, prefix): """ Display VRF Index """ # Validate vrf = self.get_object_or_404(VRF, id=int(vrf_id)) if (afi == "4" and (not is_ipv4_prefix(prefix)) or not vrf.afi_ipv4) or ( afi == "6" and (not is_ipv6_prefix(prefix) or not vrf.afi_ipv6) ): return self.response_forbidden("Invalid prefix") prefix = self.get_object_or_404(Prefix, vrf=vrf, afi=afi, prefix=prefix) # Get prefix path path = [] p = prefix.parent while p: path = [p] + path p = p.parent # List of nested prefixes # @todo: prefetch_related prefixes = list(prefix.children_set.select_related().order_by("prefix")) # Bulk utilization Prefix.update_prefixes_usage(prefixes) # Get permissions user = request.user can_view = prefix.can_view(user) can_change = prefix.can_change(user) can_bind_vc = can_change and Permission.has_perm(user, "ip:ipam:bind_vc") can_change_maintainers = user.is_superuser can_add_prefix = can_change can_add_address = can_change and len(prefixes) == 0 can_edit_special = prefix.effective_prefix_special_address == "I" # Bookmarks has_bookmark = prefix.has_bookmark(user) bookmarks = PrefixBookmark.user_bookmarks(user, vrf=vrf, afi=afi) s_bookmarks = set(b.prefix for b in bookmarks) # Add free prefixes free_prefixes = list(IP.prefix(prefix.prefix).iter_free([pp.prefix for pp in prefixes])) l_prefixes = sorted( ( [(True, IP.prefix(pp.prefix), pp, pp.prefix in s_bookmarks) for pp in prefixes] + [(False, pp, None, None) for pp in free_prefixes] ), key=lambda x: x[1], ) # List of nested addresses # @todo: prefetch_related addresses = list(prefix.address_set.select_related().order_by("address")) # Prepare block info prefix_info = [("Network", prefix.prefix)] if afi == "4": prefix_info += [ ("Broadcast", prefix.broadcast), ("Netmask", prefix.netmask), ("Widlcard", prefix.wildcard), ("Size", prefix.size), ("Usage", prefix.usage_percent), ("Usage Address", prefix.address_usage_percent), ] if addresses: prefix_info += [("Used addresses", len(addresses))] if afi == "4": free = prefix.size - len(addresses) prefix_info += [("Free addresses", free - 2 if free >= 2 else free)] # Prefix discovery dmap = {"E": "Enabled", "D": "Disabled"} if prefix.prefix_discovery_policy == "P": t = "Profile (%s)" % dmap[prefix.profile.prefix_discovery_policy] else: t = dmap[prefix.prefix_discovery_policy] prefix_info += [("Prefix Discovery", t)] # Address discovery if prefix.address_discovery_policy == "P": t = "Profile (%s)" % dmap[prefix.profile.address_discovery_policy] else: t = dmap[prefix.address_discovery_policy] prefix_info += [("Address Discovery", t)] # Source prefix_info += [ ( "Source", {"M": "Manual", "i": "Interface", "w": "Whois Route", "n": "Neighbor"}.get( prefix.source, "-" ), ) ] # # Add custom fields for f in CustomField.table_fields("ip_prefix"): v = getattr(prefix, f.name) prefix_info += [(f.label, v if v is not None else "")] # Ranges ranges = [] rs = [] max_slots = 0 r_spots = [] if addresses: # Assign ranges colors ranges = list(prefix.address_ranges) for r, c in zip(ranges, get_colors(len(ranges))): r.color = c # Schedule ranges r_changes = {} # Address -> (set of entering ranges, set of leaving ranges) for r in ranges: if r.from_address not in r_changes: r_changes[r.from_address] = (set(), set()) if r.to_address not in r_changes: r_changes[r.to_address] = (set(), set()) r_changes[r.from_address][0].add(r) r_changes[r.to_address][1].add(r) # <!> n = (IP.prefix(r.to_address) + 1).address if n not in r_changes: r_changes[n] = (set(), set()) r_spots = list(six.iterkeys(r_changes)) # Allocate slots used_slots = set() free_slots = set() r_slots = {} # Range -> slot max_slots = 0 rs = sorted( ([IP.prefix(i), d, []] for i, d in six.iteritems(r_changes)), key=itemgetter(0) ) for address, d, x in rs: entering, leaving = d for r in entering: if not free_slots: free_slots.add(max_slots) max_slots += 1 s = free_slots.pop() used_slots.add(s) r_slots[r] = s for r in leaving: s = r_slots[r] used_slots.remove(s) free_slots.add(s) # Assign ranges to slots slots = [None] * max_slots for r in rs: address, [entering, leaving], _ = r for e in entering: slots[r_slots[e]] = e r[2] = slots[:] for l in leaving: slots[r_slots[l]] = None # Assign slots to addresses c = [None] * max_slots rrs = rs[:] cr = rrs.pop(0) if rrs else None for a in addresses: address = IP.prefix(a.address) while cr and address >= cr[0]: c = cr[2] if rrs: cr = rrs.pop(0) else: break a.slots = c # Address spot if can_add_address: special_addr = IP.prefix(prefix.prefix).special_addresses c = [None] * max_slots rrs = rs[:] if rrs: cr = rrs.pop(0) else: cr = None spot = [] for a in self.get_prefix_spot(prefix, extra=r_spots): if cr and a is not None and a == cr[0]: c = [None if cc is None else cc.id for cc in cr[2]] if rrs: cr = rrs.pop(0) spot += [(None if a is None else a.address, c, a in special_addr)] spot = ujson.dumps(spot) else: spot = None can_ping = spot is not None and len([a for a in addresses if a.managed_object]) > 0 # Build custom styles styles = {} if prefix.profile.style: styles[prefix.profile.style.css_class_name] = prefix.profile.style.css for p in prefixes: if p.profile.style and p.profile.style.css_class_name not in styles: styles[p.profile.style.css_class_name] = p.profile.style.css for a in addresses: if a.profile.style and a.profile.style.css_class_name not in styles: styles[a.profile.style.css_class_name] = a.profile.style.css styles = "\n".join(six.itervalues(styles)) # Render return self.render( request, "vrf_index.html.j2", user=request.user, vrf=vrf, prefix=prefix, path=path, prefixes=prefixes, addresses=addresses, prefix_info=prefix_info, display_empty_message=not addresses and not prefixes, can_view=can_view, can_change=can_change, can_bind_vc=can_bind_vc, can_change_maintainers=can_change_maintainers, can_add_prefix=can_add_prefix, can_add_address=can_add_address, can_edit_special=can_edit_special, has_bookmark=has_bookmark, bookmarks=bookmarks, spot=spot, can_ping=can_ping, styles=styles, ranges=ranges, max_slots=max_slots, l_prefixes=l_prefixes, )
def test_is_ipv4_prefix(raw, expected): assert is_ipv4_prefix(raw) is expected