diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py index 9b05d8026..63e545abc 100644 --- a/netbox/dcim/models/racks.py +++ b/netbox/dcim/models/racks.py @@ -22,7 +22,7 @@ from utilities.choices import ColorChoices from utilities.fields import ColorField, NaturalOrderingField from utilities.querysets import RestrictedQuerySet from utilities.mptt import TreeManager -from utilities.utils import array_to_string, serialize_object +from utilities.utils import array_to_string, serialize_object, UtilizationData from .device_components import PowerOutlet, PowerPort from .devices import Device from .power import PowerFeed @@ -505,9 +505,10 @@ class Rack(ChangeLoggedModel, CustomFieldModel): return self.devices.filter(position=0) def get_utilization(self): - """ - Determine the utilization rate of the rack and return it as a percentage. Occupied and reserved units both count - as utilized. + """Gets utilization numerator and denominator for racks. + + Returns: + UtilizationData: (numerator=Occupied Unit Count, denominator=U Height of the rack) """ # Determine unoccupied units available_units = self.get_available_units() @@ -517,19 +518,19 @@ class Rack(ChangeLoggedModel, CustomFieldModel): if u in available_units: available_units.remove(u) - occupied_unit_count = self.u_height - len(available_units) - # Return the numerator and denominator as percentage is to be calculated later where needed - return (occupied_unit_count, self.u_height) + return UtilizationData(numerator=self.u_height - len(available_units), denominator=self.u_height) def get_power_utilization(self): - """ - Determine the utilization rate of power in the rack and return it as a percentage. + """Determine the utilization numerator and denominator for power utilization on the rack. + + Returns: + UtilizationData: (numerator, denominator) """ powerfeeds = PowerFeed.objects.filter(rack=self) available_power_total = sum(pf.available_power for pf in powerfeeds) if not available_power_total: - return (0, 0) + return UtilizationData(numerator=0, denominator=0) pf_powerports = PowerPort.objects.filter( _cable_peer_type=ContentType.objects.get_for_model(PowerFeed), @@ -541,7 +542,7 @@ class Rack(ChangeLoggedModel, CustomFieldModel): _cable_peer_id__in=poweroutlets.values_list('id', flat=True) ).aggregate(Sum('allocated_draw'))['allocated_draw__sum'] or 0 - return (allocated_draw_total, available_power_total) + return UtilizationData(numerator=allocated_draw_total, denominator=available_power_total) @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') diff --git a/netbox/dcim/tables/template_code.py b/netbox/dcim/tables/template_code.py index 1f67c5d7d..67675e468 100644 --- a/netbox/dcim/tables/template_code.py +++ b/netbox/dcim/tables/template_code.py @@ -82,9 +82,10 @@ RACKGROUP_ELEVATIONS = """ """ +# Value is a namedtuple that takes a numerator and denominator to pass in. UTILIZATION_GRAPH = """ {% load helpers %} -{% utilization_graph value.0 value.1 %} +{% utilization_graph value %} """ # diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index af950b149..dcd9f248d 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -14,7 +14,7 @@ from dcim.models import Device, Interface from extras.models import ChangeLoggedModel, CustomFieldModel, ObjectChange, TaggedItem from extras.utils import extras_features from utilities.querysets import RestrictedQuerySet -from utilities.utils import array_to_string, serialize_object +from utilities.utils import array_to_string, serialize_object, UtilizationData from virtualization.models import VirtualMachine, VMInterface from .choices import * from .constants import * @@ -308,13 +308,26 @@ class Aggregate(ChangeLoggedModel, CustomFieldModel): return self.prefix.version return None - def get_utilization(self): + + def get_percent_utilized(self): + """Gets the percentage utilized from the get_utilization method. + + Returns + float: Percentage utilization """ - Determine the prefix utilization of the aggregate and return it as a percentage. + utilization = self.get_utilization() + return int(utilization.numerator / float(utilization.denominator) * 100) + + + def get_utilization(self): + """Gets the numerator and denominator for calculating utilization of an Aggregrate. + Returns: + UtilizationData: Aggregate utilization (numerator=size of child prefixes, denominator=prefix size) """ queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) child_prefixes = netaddr.IPSet([p.prefix for p in queryset]) - return (child_prefixes.size, self.prefix.size) + + return UtilizationData(numerator=child_prefixes.size, denominator=self.prefix.size) class Role(ChangeLoggedModel): @@ -595,24 +608,25 @@ class Prefix(ChangeLoggedModel, CustomFieldModel): return '{}/{}'.format(next(available_ips.__iter__()), self.prefix.prefixlen) def get_utilization(self): + """Get the child prefix size and parent size. + + For Prefixes with a status of "container", get the number child prefixes. For all others, count child IP addresses. + + Returns: + UtilizationData (namedtuple): (numerator, denominator) """ - 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( - prefix__net_contained=str(self.prefix), - vrf=self.vrf - ) + if self.status == Prefix.STATUS_CONTAINER: + queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf) child_prefixes = netaddr.IPSet([p.prefix for p in queryset]) - return (child_prefixes.size, self.prefix.size) + return UtilizationData(numerator=child_prefixes.size, denominator=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 (child_count, prefix_size) + return UtilizationData(numerator=child_count, denominator=prefix_size) @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 70c515f9a..e0a711a4d 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -225,7 +225,7 @@ {{ utilization.allocated }}VA {% if powerfeed.available_power %} {{ powerfeed.available_power }}VA - {% utilization_graph utilization.allocated powerfeed.available_power %} + {% utilization_graph_raw_data utilization.allocated powerfeed.available_power %} {% else %} — — @@ -238,7 +238,7 @@ {{ leg.allocated }} {{ powerfeed.available_power|divide:3 }}VA {% with phase_available=powerfeed.available_power|divide:3 %} - {% utilization_graph leg.allocated phase_available %} + {% utilization_graph_raw_data leg.allocated phase_available %} {% endwith %} {% endfor %} diff --git a/netbox/templates/dcim/powerfeed.html b/netbox/templates/dcim/powerfeed.html index a225fb796..a4980ab54 100644 --- a/netbox/templates/dcim/powerfeed.html +++ b/netbox/templates/dcim/powerfeed.html @@ -113,7 +113,7 @@ {{ utilization.allocated }}VA / {{ object.available_power }}VA {% if object.available_power > 0 %} - {% utilization_graph utilization.allocated object.available_power %} + {% utilization_graph_raw_data utilization.allocated object.available_power %} {% endif %} {% else %} diff --git a/netbox/templates/dcim/rack.html b/netbox/templates/dcim/rack.html index f310465fb..627d77066 100644 --- a/netbox/templates/dcim/rack.html +++ b/netbox/templates/dcim/rack.html @@ -242,7 +242,7 @@ {% with power_port=powerfeed.connected_endpoint %} {% if power_port %} - {% utilization_graph power_port.get_power_draw.allocated powerfeed.available_power %} + {% utilization_graph power_port.get_power_draw %} {% else %} N/A {% endif %} diff --git a/netbox/templates/ipam/aggregate.html b/netbox/templates/ipam/aggregate.html index ce8cb0a19..1c67a06cb 100644 --- a/netbox/templates/ipam/aggregate.html +++ b/netbox/templates/ipam/aggregate.html @@ -77,7 +77,7 @@ Utilization - {{ object.get_utilization }}% + {{ object.get_percent_utilized }}% diff --git a/netbox/templates/utilities/templatetags/utilization_graph.html b/netbox/templates/utilities/templatetags/utilization_graph.html index 780ab1f68..1b9504a06 100644 --- a/netbox/templates/utilities/templatetags/utilization_graph.html +++ b/netbox/templates/utilities/templatetags/utilization_graph.html @@ -1,4 +1,4 @@ -
{% if utilization < 30 %}{{ utilization }}%{% endif %}