Просмотр исходного кода

Fixes #3458: Prevent primary IP address for a device/VM from being reassigned

Jeremy Stretch 6 лет назад
Родитель
Сommit
896d58fc3f
2 измененных файлов с 31 добавлено и 1 удалено
  1. 1 0
      CHANGELOG.md
  2. 30 1
      netbox/ipam/models.py

+ 1 - 0
CHANGELOG.md

@@ -2,6 +2,7 @@ v2.6.6 (FUTURE)
 
 ## Bug Fixes
 
+* [#3458](https://github.com/netbox-community/netbox/issues/3458) - Prevent primary IP address for a device/VM from being reassigned
 * [#3463](https://github.com/netbox-community/netbox/issues/3463) - Correct CSV headers for exported power feeds
 * [#3474](https://github.com/netbox-community/netbox/issues/3474) - Fix device status page loading when NAPALM call fails
 * [#3571](https://github.com/netbox-community/netbox/issues/3571) - Prevent erroneous redirects when editing tags

+ 30 - 1
netbox/ipam/models.py

@@ -9,10 +9,11 @@ from django.db.models.expressions import RawSQL
 from django.urls import reverse
 from taggit.managers import TaggableManager
 
-from dcim.models import Interface
+from dcim.models import Device, Interface
 from extras.models import CustomFieldModel, ObjectChange, TaggedItem
 from utilities.models import ChangeLoggedModel
 from utilities.utils import serialize_object
+from virtualization.models import VirtualMachine
 from .constants import *
 from .fields import IPNetworkField, IPAddressField
 from .querysets import PrefixQuerySet
@@ -636,6 +637,34 @@ class IPAddress(ChangeLoggedModel, CustomFieldModel):
                         )
                     })
 
+        if self.pk:
+
+            # Check for primary IP assignment that doesn't match the assigned device/VM
+            device = Device.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first()
+            if device:
+                if self.interface is None:
+                    raise ValidationError({
+                        'interface': "IP address is primary for device {} but not assigned".format(device)
+                    })
+                elif (device.primary_ip4 == self or device.primary_ip6 == self) and self.interface.device != device:
+                    raise ValidationError({
+                        'interface': "IP address is primary for device {} but assigned to {} ({})".format(
+                            device, self.interface.device, self.interface
+                        )
+                    })
+            vm = VirtualMachine.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first()
+            if vm:
+                if self.interface is None:
+                    raise ValidationError({
+                        'interface': "IP address is primary for virtual machine {} but not assigned".format(vm)
+                    })
+                elif (vm.primary_ip4 == self or vm.primary_ip6 == self) and self.interface.virtual_machine != vm:
+                    raise ValidationError({
+                        'interface': "IP address is primary for virtual machine {} but assigned to {} ({})".format(
+                            vm, self.interface.virtual_machine, self.interface
+                        )
+                    })
+
     def save(self, *args, **kwargs):
 
         # Record address family