mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Merge v2.11.11
This commit is contained in:
@ -4,7 +4,8 @@ from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
|
||||
from extras.forms import (
|
||||
AddRemoveTagsForm, CustomFieldModelBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldModelFilterForm,
|
||||
AddRemoveTagsForm, CustomFieldModelBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm,
|
||||
CustomFieldModelFilterForm,
|
||||
)
|
||||
from extras.models import Tag
|
||||
from tenancy.forms import TenancyFilterForm, TenancyForm
|
||||
@ -12,8 +13,8 @@ from tenancy.models import Tenant
|
||||
from utilities.forms import (
|
||||
add_blank_choice, BootstrapMixin, BulkEditNullBooleanSelect, ContentTypeChoiceField, CSVChoiceField,
|
||||
CSVContentTypeField, CSVModelChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
|
||||
ExpandableIPAddressField, NumericArrayField, ReturnURLForm, SlugField, StaticSelect, StaticSelectMultiple,
|
||||
TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
|
||||
ExpandableIPAddressField, NumericArrayField, SlugField, StaticSelect, StaticSelectMultiple, TagFilterField,
|
||||
BOOLEAN_WITH_BLANK_CHOICES,
|
||||
)
|
||||
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
|
||||
from .choices import *
|
||||
@ -882,7 +883,7 @@ class IPRangeFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilte
|
||||
# IP addresses
|
||||
#
|
||||
|
||||
class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModelForm):
|
||||
class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
|
@ -811,18 +811,15 @@ class IPAddress(PrimaryModel):
|
||||
|
||||
# Check for primary IP assignment that doesn't match the assigned device/VM
|
||||
if self.pk:
|
||||
device = Device.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first()
|
||||
if device:
|
||||
if getattr(self.assigned_object, 'device', None) != device:
|
||||
raise ValidationError({
|
||||
'interface': f"IP address is primary for device {device} but not assigned to it!"
|
||||
})
|
||||
vm = VirtualMachine.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first()
|
||||
if vm:
|
||||
if getattr(self.assigned_object, 'virtual_machine', None) != vm:
|
||||
raise ValidationError({
|
||||
'vminterface': f"IP address is primary for virtual machine {vm} but not assigned to it!"
|
||||
})
|
||||
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) != parent:
|
||||
# Check for a NAT relationship
|
||||
if not self.nat_inside or getattr(self.nat_inside.assigned_object, attr) != 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:
|
||||
|
@ -283,19 +283,20 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
||||
messages.success(request, mark_safe(msg))
|
||||
|
||||
if '_addanother' in request.POST:
|
||||
redirect_url = request.path
|
||||
return_url = request.GET.get('return_url')
|
||||
if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()):
|
||||
redirect_url = f'{redirect_url}?return_url={return_url}'
|
||||
|
||||
# If the object has clone_fields, pre-populate a new instance of the form
|
||||
if hasattr(obj, 'clone_fields'):
|
||||
url = '{}?{}'.format(request.path, prepare_cloned_fields(obj))
|
||||
return redirect(url)
|
||||
redirect_url += f"{'&' if return_url else '?'}{prepare_cloned_fields(obj)}"
|
||||
|
||||
return redirect(request.get_full_path())
|
||||
return redirect(redirect_url)
|
||||
|
||||
return_url = form.cleaned_data.get('return_url')
|
||||
if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()):
|
||||
return redirect(return_url)
|
||||
else:
|
||||
return redirect(self.get_return_url(request, obj))
|
||||
return_url = self.get_return_url(request, obj)
|
||||
|
||||
return redirect(return_url)
|
||||
|
||||
except PermissionsViolation:
|
||||
msg = "Object save failed due to object-level permissions violation"
|
||||
|
Reference in New Issue
Block a user