diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 45b241d4..0b6c6ccb 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -2055,14 +2055,30 @@ class PowerPort(CableTermination, ComponentModel): if self._connected_powerfeed and self._connected_powerfeed.phase == POWERFEED_PHASE_3PHASE: for leg, leg_name in POWERFEED_LEG_CHOICES: 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( - maximum_draw_total=Sum('maximum_draw'), - allocated_draw_total=Sum('allocated_draw'), - ) + power_draw_sum = PowerPort.objects.raw(""" + WITH RECURSIVE connection(outlet_id, port_id, allocated_draw, maximum_draw) AS ( + -- get all outlet and connected port pairs for given root_powerport and leg + SELECT outlet.id, connected_powerport.id, connected_powerport.allocated_draw, connected_powerport.maximum_draw + FROM dcim_powerport AS root_powerport + JOIN dcim_poweroutlet as outlet ON outlet.device_id = root_powerport.device_id + JOIN dcim_powerport AS connected_powerport ON connected_powerport._connected_poweroutlet_id=outlet.id + WHERE root_powerport.id = %s AND outlet.feed_leg = %s + + UNION ALL + + -- get all outlet and connected port pairs, using each connected port from previous step as root + SELECT outlet.id, connected_powerport.id, connected_powerport.allocated_draw, connected_powerport.maximum_draw + FROM connection + JOIN dcim_powerport AS root_powerport ON root_powerport.id = connection.port_id + JOIN dcim_poweroutlet AS outlet ON outlet.device_id = root_powerport.device_id + JOIN dcim_powerport AS connected_powerport ON connected_powerport._connected_poweroutlet_id=outlet.id + ) + SELECT 0 AS id, SUM(allocated_draw) as total_allocated_draw, SUM(maximum_draw) as total_maximum_draw FROM connection; + """, [self.id, leg]) ret['legs'].append({ 'name': leg_name, - 'allocated': utilization['allocated_draw_total'] or 0, - 'maximum': utilization['maximum_draw_total'] or 0, + 'allocated': power_draw_sum[0].total_allocated_draw, + 'maximum': power_draw_sum[0].total_maximum_draw, 'outlet_count': len(outlet_ids), })