mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #5038: Fix validation of primary IPs assigned to virtual machines
This commit is contained in:
@ -1,5 +1,13 @@
|
|||||||
# NetBox v2.9
|
# NetBox v2.9
|
||||||
|
|
||||||
|
## v2.9.2 (FUTURE)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* [#5038](https://github.com/netbox-community/netbox/issues/5038) - Fix validation of primary IPs assigned to virtual machines
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v2.9.1 (2020-08-22)
|
## v2.9.1 (2020-08-22)
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
|
@ -1811,7 +1811,7 @@ class DeviceForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
|
|||||||
nat_inside__assigned_object_id__in=interface_ids
|
nat_inside__assigned_object_id__in=interface_ids
|
||||||
).prefetch_related('assigned_object')
|
).prefetch_related('assigned_object')
|
||||||
if nat_ips:
|
if nat_ips:
|
||||||
ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in nat_ips]
|
ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips]
|
||||||
ip_choices.append(('NAT IPs', ip_list))
|
ip_choices.append(('NAT IPs', ip_list))
|
||||||
self.fields['primary_ip{}'.format(family)].choices = ip_choices
|
self.fields['primary_ip{}'.format(family)].choices = ip_choices
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from dcim.choices import InterfaceModeChoices
|
from dcim.choices import InterfaceModeChoices
|
||||||
@ -325,28 +326,28 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
|
|||||||
# Compile list of choices for primary IPv4 and IPv6 addresses
|
# Compile list of choices for primary IPv4 and IPv6 addresses
|
||||||
for family in [4, 6]:
|
for family in [4, 6]:
|
||||||
ip_choices = [(None, '---------')]
|
ip_choices = [(None, '---------')]
|
||||||
|
|
||||||
|
# Gather PKs of all interfaces belonging to this VM
|
||||||
|
interface_ids = self.instance.interfaces.values_list('pk', flat=True)
|
||||||
|
|
||||||
# Collect interface IPs
|
# Collect interface IPs
|
||||||
interface_ips = IPAddress.objects.prefetch_related('interface').filter(
|
interface_ips = IPAddress.objects.filter(
|
||||||
address__family=family,
|
address__family=family,
|
||||||
vminterface__in=self.instance.interfaces.values_list('id', flat=True)
|
assigned_object_type=ContentType.objects.get_for_model(VMInterface),
|
||||||
|
assigned_object_id__in=interface_ids
|
||||||
)
|
)
|
||||||
if interface_ips:
|
if interface_ips:
|
||||||
ip_choices.append(
|
ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in interface_ips]
|
||||||
('Interface IPs', [
|
ip_choices.append(('Interface IPs', ip_list))
|
||||||
(ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips
|
|
||||||
])
|
|
||||||
)
|
|
||||||
# Collect NAT IPs
|
# Collect NAT IPs
|
||||||
nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter(
|
nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter(
|
||||||
address__family=family,
|
address__family=family,
|
||||||
nat_inside__vminterface__in=self.instance.interfaces.values_list('id', flat=True)
|
nat_inside__assigned_object_type=ContentType.objects.get_for_model(VMInterface),
|
||||||
|
nat_inside__assigned_object_id__in=interface_ids
|
||||||
)
|
)
|
||||||
if nat_ips:
|
if nat_ips:
|
||||||
ip_choices.append(
|
ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips]
|
||||||
('NAT IPs', [
|
ip_choices.append(('NAT IPs', ip_list))
|
||||||
(ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips
|
|
||||||
])
|
|
||||||
)
|
|
||||||
self.fields['primary_ip{}'.format(family)].choices = ip_choices
|
self.fields['primary_ip{}'.format(family)].choices = ip_choices
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -335,13 +335,13 @@ class VirtualMachine(ChangeLoggedModel, ConfigContextModel, CustomFieldModel):
|
|||||||
for field in ['primary_ip4', 'primary_ip6']:
|
for field in ['primary_ip4', 'primary_ip6']:
|
||||||
ip = getattr(self, field)
|
ip = getattr(self, field)
|
||||||
if ip is not None:
|
if ip is not None:
|
||||||
if ip.interface in interfaces:
|
if ip.assigned_object in interfaces:
|
||||||
pass
|
pass
|
||||||
elif self.primary_ip4.nat_inside is not None and self.primary_ip4.nat_inside.interface in interfaces:
|
elif ip.nat_inside is not None and ip.nat_inside.assigned_object in interfaces:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
field: "The specified IP address ({}) is not assigned to this VM.".format(ip),
|
field: f"The specified IP address ({ip}) is not assigned to this VM.",
|
||||||
})
|
})
|
||||||
|
|
||||||
def to_csv(self):
|
def to_csv(self):
|
||||||
|
Reference in New Issue
Block a user