diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 857529e83..aa09f3f19 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -16,6 +16,7 @@ * [#10579](https://github.com/netbox-community/netbox/issues/10579) - Mark cable traces terminating to a provider network as complete * [#10721](https://github.com/netbox-community/netbox/issues/10721) - Disable ordering by custom object field columns * [#10929](https://github.com/netbox-community/netbox/issues/10929) - Raise validation error when attempting to create a duplicate cable termination +* [#10936](https://github.com/netbox-community/netbox/issues/10936) - Permit demotion of device/VM primary IP via IP address edit form * [#10938](https://github.com/netbox-community/netbox/issues/10938) - `render_field` template tag should respect `label` kwarg * [#10969](https://github.com/netbox-community/netbox/issues/10969) - Update cable paths ending at associated rear port when creating new front ports diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index 456bab4f0..1859ef3e1 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -8,8 +8,6 @@ from django.urls import reverse from django.utils.functional import cached_property from dcim.fields import ASNField -from dcim.models import Device -from netbox.models import OrganizationalModel, NetBoxModel from ipam.choices import * from ipam.constants import * from ipam.fields import IPNetworkField, IPAddressField @@ -17,8 +15,7 @@ from ipam.managers import IPAddressManager from ipam.querysets import PrefixQuerySet from ipam.validators import DNSValidator from netbox.config import get_config -from virtualization.models import VirtualMachine - +from netbox.models import OrganizationalModel, NetBoxModel __all__ = ( 'Aggregate', @@ -912,18 +909,6 @@ class IPAddress(NetBoxModel): ) }) - # Check for primary IP assignment that doesn't match the assigned device/VM - if self.pk: - for cls, attr in ((Device, 'device'), (VirtualMachine, 'virtual_machine')): - parent = cls.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first() - if parent and getattr(self.assigned_object, attr, None) != parent: - # Check for a NAT relationship - if not self.nat_inside or getattr(self.nat_inside.assigned_object, attr, None) != parent: - raise ValidationError({ - 'interface': f"IP address is primary for {cls._meta.model_name} {parent} but " - f"not assigned to it!" - }) - # Validate IP status selection if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6: raise ValidationError({