Optimize replication of port mappings from DeviceType

This commit is contained in:
Jeremy Stretch 2025-11-26 11:48:50 -05:00
parent ca880218d9
commit 06447ac637
3 changed files with 32 additions and 20 deletions

View File

@ -1,8 +1,7 @@
import decimal
import yaml
from functools import cached_property
import yaml
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
@ -25,17 +24,15 @@ from extras.querysets import ConfigContextModelQuerySet
from netbox.choices import ColorChoices
from netbox.config import ConfigItem
from netbox.models import NestedGroupModel, OrganizationalModel, PrimaryModel
from netbox.models.mixins import WeightMixin
from netbox.models.features import ContactsMixin, ImageAttachmentsMixin
from netbox.models.mixins import WeightMixin
from utilities.fields import ColorField, CounterCacheField
from utilities.prefetch import get_prefetchable_fields
from utilities.tracking import TrackingModelMixin
from . import PortTemplateMapping
from .device_components import *
from .mixins import RenderConfigMixin
from .modules import Module
__all__ = (
'Device',
'DeviceRole',
@ -1004,6 +1001,8 @@ class Device(
self._instantiate_components(self.device_type.interfacetemplates.all())
self._instantiate_components(self.device_type.rearporttemplates.all())
self._instantiate_components(self.device_type.frontporttemplates.all())
# Replicate any front/rear port mappings from the DeviceType
create_port_mappings(self, self.device_type)
# Disable bulk_create to accommodate MPTT
self._instantiate_components(self.device_type.modulebaytemplates.all(), bulk_create=False)
self._instantiate_components(self.device_type.devicebaytemplates.all())
@ -1011,10 +1010,6 @@ class Device(
self._instantiate_components(self.device_type.inventoryitemtemplates.all(), bulk_create=False)
# Interface bridges have to be set after interface instantiation
update_interface_bridges(self, self.device_type.interfacetemplates.all())
# Replicate any front/rear port mappings from the DeviceType
create_port_mappings(self, PortTemplateMapping.objects.filter(
front_port__device_type=self.device_type
))
# Update Site and Rack assignment for any child Devices
devices = Device.objects.filter(parent_bay__device=self)

View File

@ -537,6 +537,8 @@ class DeviceTestCase(TestCase):
)
self.assertEqual(frontport.cf['cf1'], 'foo')
self.assertTrue(PortMapping.objects.filter(front_port=frontport, rear_port=rearport).exists())
modulebay = ModuleBay.objects.get(
device=device,
name='Module Bay 1'

View File

@ -85,20 +85,35 @@ def update_interface_bridges(device, interface_templates, module=None):
interface.save()
def create_port_mappings(device, templates, module=None):
def create_port_mappings(device, device_type, module=None):
"""
Replicate all front/rear port mappings from a DeviceType to the given device.
"""
from dcim.models.device_components import FrontPort, PortMapping, RearPort
from dcim.models import FrontPort, PortMapping, PortTemplateMapping, RearPort
templates = PortTemplateMapping.objects.filter(
front_port__device_type=device_type
).prefetch_related('front_port', 'rear_port')
# Cache front & rear ports for efficient lookups by name
front_ports = {
fp.name: fp for fp in FrontPort.objects.filter(device=device)
}
rear_ports = {
rp.name: rp for rp in RearPort.objects.filter(device=device)
}
# Replicate PortMappings
mappings = []
for template in templates:
front_port = FrontPort.objects.get(device=device, name=template.front_port.resolve_name(module=module))
rear_port = RearPort.objects.get(device=device, name=template.rear_port.resolve_name(module=module))
assignment = PortMapping(
front_port=front_port,
front_port_position=template.front_port_position,
rear_port=rear_port,
rear_port_position=template.rear_port_position,
front_port = front_ports.get(template.front_port.resolve_name(module=module))
rear_port = rear_ports.get(template.rear_port.resolve_name(module=module))
mappings.append(
PortMapping(
front_port=front_port,
front_port_position=template.front_port_position,
rear_port=rear_port,
rear_port_position=template.rear_port_position,
)
)
assignment.save()
PortMapping.objects.bulk_create(mappings)