Parcourir la source

Initial work on #289

Jeremy Stretch il y a 8 ans
Parent
commit
57373c9d6f
2 fichiers modifiés avec 48 ajouts et 2 suppressions
  1. 11 1
      netbox/ipam/tables.py
  2. 37 1
      netbox/ipam/views.py

+ 11 - 1
netbox/ipam/tables.py

@@ -39,6 +39,16 @@ PREFIX_LINK_BRIEF = """
 </span>
 """
 
+IPADDRESS_LINK = """
+{% if record.pk %}
+    <a href="{{ record.get_absolute_url }}">{{ record.address }}</a>
+{% elif perms.ipam.add_ipaddress %}
+    <a href="{% url 'ipam:ipaddress_add' %}?address={{ record.1 }}" class="btn btn-xs btn-success">{{ record.0 }} free IP{{ record.0|pluralize }}</a>
+{% else %}
+    {{ record.0 }}
+{% endif %}
+"""
+
 STATUS_LABEL = """
 {% if record.pk %}
     <span class="label label-{{ record.get_status_class }}">{{ record.get_status_display }}</span>
@@ -169,7 +179,7 @@ class PrefixBriefTable(BaseTable):
 
 class IPAddressTable(BaseTable):
     pk = ToggleColumn()
-    address = tables.LinkColumn('ipam:ipaddress', args=[Accessor('pk')], verbose_name='IP Address')
+    address = tables.TemplateColumn(IPADDRESS_LINK, verbose_name='IP Address')
     vrf = tables.LinkColumn('ipam:vrf', args=[Accessor('vrf.pk')], default='Global', verbose_name='VRF')
     tenant = tables.TemplateColumn(TENANT_LINK, verbose_name='Tenant')
     device = tables.LinkColumn('dcim:device', args=[Accessor('interface.device.pk')], orderable=False,

+ 37 - 1
netbox/ipam/views.py

@@ -1,4 +1,4 @@
-from netaddr import IPSet
+from netaddr import IPNetwork, IPSet
 from django_tables2 import RequestConfig
 
 from django.contrib.auth.mixins import PermissionRequiredMixin
@@ -31,6 +31,41 @@ def add_available_prefixes(parent, prefix_list):
     return prefix_list
 
 
+def add_available_ipaddresses(prefix, ipaddress_list):
+    """
+    Create fake IPAddress objects for all unallocated space within a prefix.
+    """
+
+    # Find all unallocated space
+    available_ips = IPSet(prefix) - IPSet([str(ip.address.ip) for ip in ipaddress_list])
+    available_ips = [IPAddress(address=IPNetwork('{}/{}'.format(ip, prefix.prefixlen))) for ip in available_ips]
+
+    # Concatenate and sort complete list of children
+    ipaddress_list = list(ipaddress_list) + available_ips
+    ipaddress_list.sort(key=lambda ip: ip.address)
+    if not ipaddress_list:
+        return []
+
+    # Summarize free IPs in the list
+    computed_list = []
+    count = 0
+    prev_ip = ipaddress_list[0]
+    for ip in ipaddress_list:
+        if ip.pk:
+            if count:
+                computed_list.append((count, prev_ip))
+                count = 0
+            computed_list.append(ip)
+            continue
+        if not count:
+            prev_ip = ip
+        count += 1
+    if count:
+        computed_list.append((count, prev_ip))
+
+    return computed_list
+
+
 #
 # VRFs
 #
@@ -375,6 +410,7 @@ def prefix_ipaddresses(request, pk):
     # Find all IPAddresses belonging to this Prefix
     ipaddresses = IPAddress.objects.filter(vrf=prefix.vrf, address__net_contained_or_equal=str(prefix.prefix))\
         .select_related('vrf', 'interface__device', 'primary_ip4_for', 'primary_ip6_for')
+    ipaddresses = add_available_ipaddresses(prefix.prefix, ipaddresses)
 
     ip_table = tables.IPAddressTable(ipaddresses)
     ip_table.model = IPAddress