Add validation and filtering for device on primary_ip4/primary_ip6 for VDC model

This commit is contained in:
Daniel Sheppard 2022-11-17 08:49:16 -06:00
parent 977b79ecee
commit a85d1b1319
3 changed files with 40 additions and 4 deletions

View File

@ -1705,6 +1705,22 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
'rack_id': '$rack',
}
)
primary_ip4 = DynamicModelChoiceField(
queryset=IPAddress.objects.all(),
required=False,
query_params={
'device_id': '$device',
'family': 4,
}
)
primary_ip6 = DynamicModelChoiceField(
queryset=IPAddress.objects.all(),
required=False,
query_params={
'device_id': '$device',
'family': 6,
}
)
fieldsets = (
('Assigned Device', ('region', 'site_group', 'site', 'location', 'rack', 'device')),
@ -1720,6 +1736,4 @@ class VirtualDeviceContextForm(TenancyForm, NetBoxModelForm):
]
widgets = {
'status': StaticSelect(),
'primary_ip4': StaticSelect(),
'primary_ip6': StaticSelect(),
}

View File

@ -1175,3 +1175,25 @@ class VirtualDeviceContext(PrimaryModel):
return self.primary_ip4
else:
return None
def clean(self):
super().clean()
vc_interfaces = self.device.vc_interfaces(if_master=False)
if self.primary_ip4:
if self.primary_ip4.family != 4:
raise ValidationError({
'primary_ip4': f"{self.primary_ip4} is not an IPv4 address."
})
if self.primary_ip4.assigned_object not in vc_interfaces:
raise ValidationError({
'primary_ip4': f"The specified IP address ({self.primary_ip4}) is not assigned to this device."
})
if self.primary_ip6:
if self.primary_ip6.family != 6:
raise ValidationError({
'primary_ip6': f"{self.primary_ip6} is not an IPv6 address."
})
if self.primary_ip6.assigned_object not in vc_interfaces:
raise ValidationError({
'primary_ip6': f"The specified IP address ({self.primary_ip6}) is not assigned to this device."
})

View File

@ -9,7 +9,7 @@ from django.utils.functional import cached_property
from django.utils.translation import gettext as _
from dcim.fields import ASNField
from dcim.models import Device
from dcim.models import Device, VirtualDeviceContext
from ipam.choices import *
from ipam.constants import *
from ipam.fields import IPNetworkField, IPAddressField
@ -866,7 +866,7 @@ class IPAddress(PrimaryModel):
# 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')):
for cls, attr in ((Device, 'device'), (VirtualMachine, 'virtual_machine'), (VirtualDeviceContext, 'device')):
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