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

#6454 fix merge conflicts

This commit is contained in:
Arthur
2022-08-18 15:31:54 -07:00
458 changed files with 14069 additions and 6039 deletions

View File

@@ -1,4 +1,4 @@
from collections import OrderedDict
import decimal
from django.apps import apps
from django.contrib.auth.models import User
@@ -14,11 +14,10 @@ from django.urls import reverse
from dcim.choices import *
from dcim.constants import *
from dcim.svg import RackElevationSVG
from netbox.config import get_config
from netbox.models import OrganizationalModel, NetBoxModel
from utilities.choices import ColorChoices
from utilities.fields import ColorField, NaturalOrderingField
from utilities.utils import array_to_string
from utilities.utils import array_to_string, drange
from .device_components import PowerOutlet, PowerPort
from .devices import Device
from .power import PowerFeed
@@ -185,10 +184,10 @@ class Rack(NetBoxModel):
to='extras.ImageAttachment'
)
clone_fields = [
clone_fields = (
'site', 'location', 'tenant', 'status', 'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit',
]
)
class Meta:
ordering = ('site', 'location', '_name', 'pk') # (site, location, name) may be non-unique
@@ -247,10 +246,12 @@ class Rack(NetBoxModel):
@property
def units(self):
"""
Return a list of unit numbers, top to bottom.
"""
if self.desc_units:
return range(1, self.u_height + 1)
else:
return reversed(range(1, self.u_height + 1))
return drange(decimal.Decimal(1.0), self.u_height + 1, 0.5)
return drange(self.u_height + decimal.Decimal(0.5), 0.5, -0.5)
def get_status_color(self):
return RackStatusChoices.colors.get(self.status)
@@ -268,12 +269,12 @@ class Rack(NetBoxModel):
reference to the device. When False, only the bottom most unit for a device is included and that unit
contains a height attribute for the device
"""
elevation = OrderedDict()
elevation = {}
for u in self.units:
u_name = f'U{u}'.split('.')[0] if not u % 1 else f'U{u}'
elevation[u] = {
'id': u,
'name': f'U{u}',
'name': u_name,
'face': face,
'device': None,
'occupied': False
@@ -283,7 +284,7 @@ class Rack(NetBoxModel):
if self.pk:
# Retrieve all devices installed within the rack
queryset = Device.objects.prefetch_related(
devices = Device.objects.prefetch_related(
'device_type',
'device_type__manufacturer',
'device_role'
@@ -304,9 +305,9 @@ class Rack(NetBoxModel):
if user is not None:
permitted_device_ids = self.devices.restrict(user, 'view').values_list('pk', flat=True)
for device in queryset:
for device in devices:
if expand_devices:
for u in range(device.position, device.position + device.device_type.u_height):
for u in drange(device.position, device.position + device.device_type.u_height, 0.5):
if user is None or device.pk in permitted_device_ids:
elevation[u]['device'] = device
elevation[u]['occupied'] = True
@@ -315,8 +316,6 @@ class Rack(NetBoxModel):
elevation[device.position]['device'] = device
elevation[device.position]['occupied'] = True
elevation[device.position]['height'] = device.device_type.u_height
for u in range(device.position + 1, device.position + device.device_type.u_height):
elevation.pop(u, None)
return [u for u in elevation.values()]
@@ -336,12 +335,12 @@ class Rack(NetBoxModel):
devices = devices.exclude(pk__in=exclude)
# Initialize the rack unit skeleton
units = list(range(1, self.u_height + 1))
units = list(self.units)
# Remove units consumed by installed devices
for d in devices:
if rack_face is None or d.face == rack_face or d.device_type.is_full_depth:
for u in range(d.position, d.position + d.device_type.u_height):
for u in drange(d.position, d.position + d.device_type.u_height, 0.5):
try:
units.remove(u)
except ValueError:
@@ -351,7 +350,7 @@ class Rack(NetBoxModel):
# Remove units without enough space above them to accommodate a device of the specified height
available_units = []
for u in units:
if set(range(u, u + u_height)).issubset(units):
if set(drange(u, u + u_height, 0.5)).issubset(units):
available_units.append(u)
return list(reversed(available_units))
@@ -361,9 +360,9 @@ class Rack(NetBoxModel):
Return a dictionary mapping all reserved units within the rack to their reservation.
"""
reserved_units = {}
for r in self.reservations.all():
for u in r.units:
reserved_units[u] = r
for reservation in self.reservations.all():
for u in reservation.units:
reserved_units[u] = reservation
return reserved_units
def get_elevation_svg(
@@ -372,9 +371,11 @@ class Rack(NetBoxModel):
user=None,
unit_width=None,
unit_height=None,
legend_width=RACK_ELEVATION_LEGEND_WIDTH_DEFAULT,
legend_width=RACK_ELEVATION_DEFAULT_LEGEND_WIDTH,
margin_width=RACK_ELEVATION_DEFAULT_MARGIN_WIDTH,
include_images=True,
base_url=None
base_url=None,
highlight_params=None
):
"""
Return an SVG of the rack elevation
@@ -386,16 +387,23 @@ class Rack(NetBoxModel):
:param unit_height: Height of each rack unit for the rendered drawing. Note this is not the total
height of the elevation
:param legend_width: Width of the unit legend, in pixels
:param margin_width: Width of the rigth-hand margin, in pixels
:param include_images: Embed front/rear device images where available
:param base_url: Base URL for links and images. If none, URLs will be relative.
"""
elevation = RackElevationSVG(self, user=user, include_images=include_images, base_url=base_url)
if unit_width is None or unit_height is None:
config = get_config()
unit_width = unit_width or config.RACK_ELEVATION_DEFAULT_UNIT_WIDTH
unit_height = unit_height or config.RACK_ELEVATION_DEFAULT_UNIT_HEIGHT
elevation = RackElevationSVG(
self,
unit_width=unit_width,
unit_height=unit_height,
legend_width=legend_width,
margin_width=margin_width,
user=user,
include_images=include_images,
base_url=base_url,
highlight_params=highlight_params
)
return elevation.render(face, unit_width, unit_height, legend_width)
return elevation.render(face)
def get_0u_devices(self):
return self.devices.filter(position=0)
@@ -406,6 +414,7 @@ class Rack(NetBoxModel):
as utilized.
"""
# Determine unoccupied units
total_units = len(list(self.units))
available_units = self.get_available_units()
# Remove reserved units
@@ -413,8 +422,8 @@ class Rack(NetBoxModel):
if u in available_units:
available_units.remove(u)
occupied_unit_count = self.u_height - len(available_units)
percentage = float(occupied_unit_count) / self.u_height * 100
occupied_unit_count = total_units - len(available_units)
percentage = float(occupied_unit_count) / total_units * 100
return percentage
@@ -427,17 +436,17 @@ class Rack(NetBoxModel):
if not available_power_total:
return 0
pf_powerports = PowerPort.objects.filter(
_link_peer_type=ContentType.objects.get_for_model(PowerFeed),
_link_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(
_link_peer_type=ContentType.objects.get_for_model(PowerOutlet),
_link_peer_id__in=poweroutlets.values_list('id', flat=True)
).aggregate(Sum('allocated_draw'))['allocated_draw__sum'] or 0
powerports = []
for powerfeed in powerfeeds:
powerports.extend([
peer for peer in powerfeed.link_peers if isinstance(peer, PowerPort)
])
return int(allocated_draw_total / available_power_total * 100)
allocated_draw = sum([
powerport.get_power_draw()['allocated'] for powerport in powerports
])
return int(allocated_draw / available_power_total * 100)
class RackReservation(NetBoxModel):