From 277acd3a3198da87f4e87816bf497be6b66e528e Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Mon, 20 Jan 2025 22:49:55 -0600 Subject: [PATCH 1/3] Fixes: #18436 - Prevent unassigning mac address when primary on an interface --- netbox/dcim/models/devices.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index dbcd91ea0..d202d5d9e 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -15,6 +15,7 @@ from django.urls import reverse from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ +from core.models import ObjectType from dcim.choices import * from dcim.constants import * from dcim.fields import MACAddressField @@ -1522,3 +1523,26 @@ class MACAddress(PrimaryModel): def __str__(self): return str(self.mac_address) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Denote the original assigned object (if any) for validation in clean() + self._original_assigned_object_id = self.__dict__.get('assigned_object_id') + self._original_assigned_object_type_id = self.__dict__.get('assigned_object_type_id') + + def clean(self, *args, **kwargs): + super().clean() + if self._original_assigned_object_id and self._original_assigned_object_type_id: + assigned_object = getattr(self.assigned_object, 'parent_object', None) + ct = ObjectType.objects.get_for_id(self._original_assigned_object_type_id) + original_assigned_object = ct.get_object_for_this_type(pk=self._original_assigned_object_id) + + if original_assigned_object and not assigned_object: + raise ValidationError( + _("Cannot unassign MAC Address while it is designated as the primary MAC for an object") + ) + elif original_assigned_object and original_assigned_object != assigned_object: + raise ValidationError( + _("Cannot reassign MAC Address while it is designated as the primary MAC for an object") + ) From 22e320084a9906159fdf2770a3c951cd80fc782b Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Mon, 20 Jan 2025 23:06:29 -0600 Subject: [PATCH 2/3] Update UI to disable interface assignment when assigned as primary --- netbox/dcim/forms/model_forms.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index 9bc69e991..5a3a27d25 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/netbox/dcim/forms/model_forms.py @@ -1810,6 +1810,11 @@ class MACAddressForm(NetBoxModelForm): super().__init__(*args, **kwargs) + if instance and instance.assigned_object and instance.assigned_object.primary_mac_address: + if instance.assigned_object.primary_mac_address.pk == instance.pk: + self.fields['interface'].disabled = True + self.fields['vminterface'].disabled = True + def clean(self): super().clean() From bec97df2426e95987959713670eb9debbb3669cf Mon Sep 17 00:00:00 2001 From: Daniel Sheppard Date: Mon, 20 Jan 2025 23:44:36 -0600 Subject: [PATCH 3/3] Fix Tests --- netbox/dcim/models/devices.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py index d202d5d9e..6ef5ab488 100644 --- a/netbox/dcim/models/devices.py +++ b/netbox/dcim/models/devices.py @@ -1534,15 +1534,16 @@ class MACAddress(PrimaryModel): def clean(self, *args, **kwargs): super().clean() if self._original_assigned_object_id and self._original_assigned_object_type_id: - assigned_object = getattr(self.assigned_object, 'parent_object', None) + assigned_object = self.assigned_object ct = ObjectType.objects.get_for_id(self._original_assigned_object_type_id) original_assigned_object = ct.get_object_for_this_type(pk=self._original_assigned_object_id) - if original_assigned_object and not assigned_object: - raise ValidationError( - _("Cannot unassign MAC Address while it is designated as the primary MAC for an object") - ) - elif original_assigned_object and original_assigned_object != assigned_object: - raise ValidationError( - _("Cannot reassign MAC Address while it is designated as the primary MAC for an object") - ) + if original_assigned_object.primary_mac_address: + if not assigned_object: + raise ValidationError( + _("Cannot unassign MAC Address while it is designated as the primary MAC for an object") + ) + elif original_assigned_object != assigned_object: + raise ValidationError( + _("Cannot reassign MAC Address while it is designated as the primary MAC for an object") + )