diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 89ee0facc..208d46c4c 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from netaddr import IPNetwork, cidr_merge +from netaddr import IPNetwork, IPSet from django.conf import settings from django.contrib.contenttypes.fields import GenericRelation @@ -206,13 +206,9 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel): """ Determine the prefix utilization of the aggregate and return it as a percentage. """ - child_prefixes = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) - # Remove overlapping prefixes from list of children - networks = cidr_merge([c.prefix for c in child_prefixes]) - children_size = float(0) - for p in networks: - children_size += p.size - return int(children_size / self.prefix.size * 100) + queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) + child_prefixes = IPSet([p.prefix for p in queryset]) + return int(float(child_prefixes.size) / self.prefix.size * 100) @python_2_unicode_compatible @@ -370,13 +366,21 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): def get_utilization(self): """ - Determine the utilization of the prefix and return it as a percentage. + Determine the utilization of the prefix and return it as a percentage. For Prefixes with a status of + "container", calculate utilization based on child prefixes. For all others, count child IP addresses. """ - child_count = IPAddress.objects.filter(address__net_contained_or_equal=str(self.prefix), vrf=self.vrf).count() - prefix_size = self.prefix.size - if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool: - prefix_size -= 2 - return int(float(child_count) / prefix_size * 100) + if self.status == PREFIX_STATUS_CONTAINER: + queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf) + child_prefixes = IPSet([p.prefix for p in queryset]) + return int(float(child_prefixes.size) / self.prefix.size * 100) + else: + child_count = IPAddress.objects.filter( + address__net_contained_or_equal=str(self.prefix), vrf=self.vrf + ).count() + prefix_size = self.prefix.size + if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool: + prefix_size -= 2 + return int(float(child_count) / prefix_size * 100) @property def new_subnet(self): diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 767bd2cec..acb29f9e0 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -241,7 +241,7 @@ class PrefixTable(BaseTable): prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}}) status = tables.TemplateColumn(STATUS_LABEL) vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF') - get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='IP Usage') + get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization') tenant = tables.TemplateColumn(TENANT_LINK) site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')]) vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN')