diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 6c5ab08b9..9bee2291a 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -542,9 +542,9 @@ class Rack(ChangeLoggedModel, CustomFieldModel): available_units.remove(u) occupied_unit_count = self.u_height - len(available_units) - percentage = int(float(occupied_unit_count) / self.u_height * 100) - return percentage + # Return the numerator and denominator as percentage is to be calculated later where needed + return (occupied_unit_count, self.u_height) def get_power_utilization(self): """ @@ -562,8 +562,8 @@ class Rack(ChangeLoggedModel, CustomFieldModel): if power_stats: allocated_draw_total = sum(x['allocated_draw_total'] or 0 for x in power_stats) available_power_total = sum(x['available_power'] for x in power_stats) - return int(allocated_draw_total / available_power_total * 100) or 0 - return 0 + return int(allocated_draw_total / available_power_total * 100) or (0, 0) + return (0, 0) @extras_features('custom_links', 'export_templates', 'webhooks') diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index bd350ef12..f0bdd4818 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -258,7 +258,7 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): """ queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) child_prefixes = netaddr.IPSet([p.prefix for p in queryset]) - return int(float(child_prefixes.size) / self.prefix.size * 100) + return (child_prefixes.size, self.prefix.size) class Role(ChangeLoggedModel): @@ -550,8 +550,8 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): def get_utilization(self): """ - 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. + Get the child prefix size and parent prefix size return them as a tuple. For Prefixes with a status of + "container", get the number child prefixes. For all others, count child IP addresses. """ if self.status == PrefixStatusChoices.STATUS_CONTAINER: queryset = Prefix.objects.filter( @@ -559,14 +559,14 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): vrf=self.vrf ) child_prefixes = netaddr.IPSet([p.prefix for p in queryset]) - return (int(float(child_prefixes.size) / self.prefix.size * 100), child_prefixes.size, self.prefix.size) + return (child_prefixes.size, self.prefix.size) else: # Compile an IPSet to avoid counting duplicate IPs child_count = netaddr.IPSet([ip.address.ip for ip in self.get_child_ips()]).size prefix_size = self.prefix.size if self.prefix.version == 4 and self.prefix.prefixlen < 31 and not self.is_pool: prefix_size -= 2 - return (int(float(child_count) / prefix_size * 100), child_count, prefix_size) + return (child_count, prefix_size) @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py index 527bc18a2..f74db47d7 100644 --- a/netbox/ipam/tests/test_models.py +++ b/netbox/ipam/tests/test_models.py @@ -179,8 +179,7 @@ class TestPrefix(TestCase): Prefix(prefix=netaddr.IPNetwork('10.0.0.0/26')), Prefix(prefix=netaddr.IPNetwork('10.0.0.128/26')), )) - self.assertEqual(prefix.get_utilization()[0], 50) - self.assertEqual(prefix.get_utilization(), (50, 128, 256)) + self.assertEqual(prefix.get_utilization(), (128, 256)) # Non-container Prefix prefix.status = PrefixStatusChoices.STATUS_ACTIVE @@ -189,8 +188,7 @@ class TestPrefix(TestCase): # Create 32 IPAddresses within the Prefix [IPAddress(address=netaddr.IPNetwork('10.0.0.{}/24'.format(i))) for i in range(1, 33)] ) - self.assertEqual(prefix.get_utilization()[0], 12) # ~= 12% - self.assertEqual(prefix.get_utilization(), (12, 32, 254)) + self.assertEqual(prefix.get_utilization(), (32, 254)) # # Uniqueness enforcement tests diff --git a/netbox/templates/utilities/templatetags/utilization_graph.html b/netbox/templates/utilities/templatetags/utilization_graph.html index c54868635..b7b97e580 100644 --- a/netbox/templates/utilities/templatetags/utilization_graph.html +++ b/netbox/templates/utilities/templatetags/utilization_graph.html @@ -1,4 +1,5 @@ -
+
{% if utilization < 30 %}{{ utilization }}%{% endif %}
diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py index bf6c9c1f1..66cb7afa3 100644 --- a/netbox/utilities/templatetags/helpers.py +++ b/netbox/utilities/templatetags/helpers.py @@ -230,23 +230,22 @@ def querystring(request, **kwargs): @register.inclusion_tag('utilities/templatetags/utilization_graph.html') -def utilization_graph(utilization, warning_threshold=75, danger_threshold=90): +def utilization_graph(data_input, warning_threshold=75, danger_threshold=90): """ Display a horizontal bar graph indicating a percentage of utilization. """ - if isinstance(utilization, int): - return { - 'utilization': utilization, - 'warning_threshold': warning_threshold, - 'danger_threshold': danger_threshold, - } + # Check for possible division by zero error + if data_input[1] == 0: + utilization = 0 + else: + utilization = int(float(data_input[0]) / data_input[1] * 100) return { - 'utilization': utilization[0], + 'utilization': utilization, 'warning_threshold': warning_threshold, 'danger_threshold': danger_threshold, - 'util_count': utilization[1], - 'num_available': utilization[2], + 'utilization_count': data_input[0], + 'num_available': data_input[1], }