1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Clean up power utilization logic

This commit is contained in:
Jeremy Stretch
2020-10-07 11:14:16 -04:00
parent f560693748
commit eaf8d95ce5
3 changed files with 35 additions and 20 deletions

View File

@ -320,8 +320,12 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
""" """
# Calculate aggregate draw of all child power outlets if no numbers have been defined manually # Calculate aggregate draw of all child power outlets if no numbers have been defined manually
if self.allocated_draw is None and self.maximum_draw is None: if self.allocated_draw is None and self.maximum_draw is None:
poweroutlet_ct = ContentType.objects.get_for_model(PowerOutlet)
outlet_ids = PowerOutlet.objects.filter(power_port=self).values_list('pk', flat=True) outlet_ids = PowerOutlet.objects.filter(power_port=self).values_list('pk', flat=True)
utilization = PowerPort.objects.filter(_connected_poweroutlet_id__in=outlet_ids).aggregate( utilization = PowerPort.objects.filter(
_cable_peer_type=poweroutlet_ct,
_cable_peer_id__in=outlet_ids
).aggregate(
maximum_draw_total=Sum('maximum_draw'), maximum_draw_total=Sum('maximum_draw'),
allocated_draw_total=Sum('allocated_draw'), allocated_draw_total=Sum('allocated_draw'),
) )
@ -333,10 +337,13 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
} }
# Calculate per-leg aggregates for three-phase feeds # Calculate per-leg aggregates for three-phase feeds
if self._connected_powerfeed and self._connected_powerfeed.phase == PowerFeedPhaseChoices.PHASE_3PHASE: if getattr(self._cable_peer, 'phase', None) == PowerFeedPhaseChoices.PHASE_3PHASE:
for leg, leg_name in PowerOutletFeedLegChoices: for leg, leg_name in PowerOutletFeedLegChoices:
outlet_ids = PowerOutlet.objects.filter(power_port=self, feed_leg=leg).values_list('pk', flat=True) outlet_ids = PowerOutlet.objects.filter(power_port=self, feed_leg=leg).values_list('pk', flat=True)
utilization = PowerPort.objects.filter(_connected_poweroutlet_id__in=outlet_ids).aggregate( utilization = PowerPort.objects.filter(
_cable_peer_type=poweroutlet_ct,
_cable_peer_id__in=outlet_ids
).aggregate(
maximum_draw_total=Sum('maximum_draw'), maximum_draw_total=Sum('maximum_draw'),
allocated_draw_total=Sum('allocated_draw'), allocated_draw_total=Sum('allocated_draw'),
) )

View File

@ -3,6 +3,7 @@ from collections import OrderedDict
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
@ -22,6 +23,7 @@ from utilities.fields import ColorField, NaturalOrderingField
from utilities.querysets import RestrictedQuerySet from utilities.querysets import RestrictedQuerySet
from utilities.mptt import TreeManager from utilities.mptt import TreeManager
from utilities.utils import array_to_string, serialize_object from utilities.utils import array_to_string, serialize_object
from .device_components import PowerOutlet, PowerPort
from .devices import Device from .devices import Device
from .power import PowerFeed from .power import PowerFeed
@ -536,21 +538,23 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
""" """
Determine the utilization rate of power in the rack and return it as a percentage. Determine the utilization rate of power in the rack and return it as a percentage.
""" """
power_stats = PowerFeed.objects.filter( powerfeeds = PowerFeed.objects.filter(rack=self)
rack=self available_power_total = sum(pf.available_power for pf in powerfeeds)
).annotate( if not available_power_total:
allocated_draw_total=Sum('connected_endpoint__poweroutlets__connected_endpoint__allocated_draw'),
).values(
'allocated_draw_total',
'available_power'
)
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 0
pf_powerports = PowerPort.objects.filter(
_cable_peer_type=ContentType.objects.get_for_model(PowerFeed),
_cable_peer_id__in=powerfeeds.values_list('id', flat=True)
)
poweroutlets = PowerOutlet.objects.filter(power_port_id__in=pf_powerports)
allocated_draw_total = PowerPort.objects.filter(
_cable_peer_type=ContentType.objects.get_for_model(PowerOutlet),
_cable_peer_id__in=poweroutlets.values_list('id', flat=True)
).aggregate(Sum('allocated_draw'))['allocated_draw__sum'] or 0
return int(allocated_draw_total / available_power_total * 100)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') @extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
class RackReservation(ChangeLoggedModel, CustomFieldModel): class RackReservation(ChangeLoggedModel, CustomFieldModel):

View File

@ -151,9 +151,13 @@
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Utilization</td> <td>Space Utilization</td>
<td>{% utilization_graph rack.get_utilization %}</td> <td>{% utilization_graph rack.get_utilization %}</td>
</tr> </tr>
<tr>
<td>Power Utilization</td>
<td>{% utilization_graph rack.get_power_utilization %}</td>
</tr>
</table> </table>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">