From f3e997ea39105d5032d02c54d26b459fd4d0c5c7 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 8 Jun 2017 12:37:25 -0400 Subject: [PATCH] Closes #40: Added IP utilization graph to prefix list --- netbox/ipam/models.py | 24 +++++++++++++++++------- netbox/ipam/tables.py | 5 +++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 04f193dd4..40e3fefde 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -200,7 +200,7 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel): def get_utilization(self): """ - Determine the utilization rate of the aggregate prefix and return it as a percentage. + 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 @@ -307,9 +307,6 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): def get_absolute_url(self): return reverse('ipam:prefix', args=[self.pk]) - def get_duplicates(self): - return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) - def clean(self): if self.prefix: @@ -357,6 +354,22 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): self.description, ]) + def get_status_class(self): + return STATUS_CHOICE_CLASSES[self.status] + + def get_duplicates(self): + return Prefix.objects.filter(vrf=self.vrf, prefix=str(self.prefix)).exclude(pk=self.pk) + + def get_utilization(self): + """ + Determine the utilization of the prefix and return it as a percentage. + """ + 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): if self.family == 4: @@ -368,9 +381,6 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): return IPNetwork('{}/{}'.format(self.prefix.network, self.prefix.prefixlen + 1)) return None - def get_status_class(self): - return STATUS_CHOICE_CLASSES[self.status] - class IPAddressManager(models.Manager): diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 64b7d62fa..767bd2cec 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -34,7 +34,7 @@ RIR_ACTIONS = """ UTILIZATION_GRAPH = """ {% load helpers %} -{% utilization_graph value %} +{% if record.pk %}{% utilization_graph value %}{% else %}—{% endif %} """ ROLE_ACTIONS = """ @@ -241,6 +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') 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') @@ -248,7 +249,7 @@ class PrefixTable(BaseTable): class Meta(BaseTable.Meta): model = Prefix - fields = ('pk', 'prefix', 'status', 'vrf', 'tenant', 'site', 'vlan', 'role', 'description') + fields = ('pk', 'prefix', 'status', 'vrf', 'get_utilization', 'tenant', 'site', 'vlan', 'role', 'description') row_attrs = { 'class': lambda record: 'success' if not record.pk else '', }