diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index 9e1d7b61e9b..dfc3ec6892a 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -632,10 +632,17 @@ def clean(self): }) # Check that the primary MAC address (if any) is assigned to this interface - if self.primary_mac_address and self.primary_mac_address.assigned_object != self: + if ( + self.primary_mac_address and + self.primary_mac_address.assigned_object is not None and + self.primary_mac_address.assigned_object != self + ): raise ValidationError({ - 'primary_mac_address': _("MAC address {mac_address} is not assigned to this interface.").format( - mac_address=self.primary_mac_address + 'primary_mac_address': _( + "MAC address {mac_address} is assigned to a different interface ({interface})." + ).format( + mac_address=self.primary_mac_address, + interface=self.primary_mac_address.assigned_object, ) }) diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index c7d3533fb4c..8f7d0d2ebdc 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -4,6 +4,7 @@ from django.dispatch import receiver from dcim.choices import CableEndChoices, LinkStatusChoices +from virtualization.models import VMInterface from .models import ( Cable, CablePath, CableTermination, ConsolePort, ConsoleServerPort, Device, DeviceBay, FrontPort, Interface, InventoryItem, ModuleBay, PathEndpoint, PowerOutlet, PowerPanel, PowerPort, Rack, RearPort, Location, @@ -170,3 +171,15 @@ def extend_rearport_cable_paths(instance, created, raw, **kwargs): rearport = instance.rear_port for cablepath in CablePath.objects.filter(_nodes__contains=rearport): cablepath.retrace() + + +@receiver(post_save, sender=Interface) +@receiver(post_save, sender=VMInterface) +def update_mac_address_interface(instance, created, raw, **kwargs): + """ + When creating a new Interface or VMInterface, check whether a MACAddress has been designated as its primary. If so, + assign the MACAddress to the interface. + """ + if created and not raw and instance.primary_mac_address: + instance.primary_mac_address.assigned_object = instance + instance.primary_mac_address.save()