1
0
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:
jeremystretch
2021-08-12 11:51:04 -04:00
7 changed files with 30 additions and 29 deletions

View File

@ -17,7 +17,7 @@ body:
What version of NetBox are you currently running? (If you don't have access to the most What version of NetBox are you currently running? (If you don't have access to the most
recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/) recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/)
before opening a bug report to see if your issue has already been addressed.) before opening a bug report to see if your issue has already been addressed.)
placeholder: v2.11.10 placeholder: v2.11.11
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

View File

@ -14,7 +14,7 @@ body:
attributes: attributes:
label: NetBox version label: NetBox version
description: What version of NetBox are you currently running? description: What version of NetBox are you currently running?
placeholder: v2.11.10 placeholder: v2.11.11
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

View File

@ -1,6 +1,6 @@
# NetBox v2.11 # NetBox v2.11
## v2.11.11 (FUTURE) ## v2.11.11 (2021-08-12)
### Enhancements ### Enhancements
@ -11,10 +11,12 @@
* [#6740](https://github.com/netbox-community/netbox/issues/6740) - Add import button to VM interfaces list * [#6740](https://github.com/netbox-community/netbox/issues/6740) - Add import button to VM interfaces list
* [#6892](https://github.com/netbox-community/netbox/issues/6892) - Fix validation of unit ranges when creating a rack reservation * [#6892](https://github.com/netbox-community/netbox/issues/6892) - Fix validation of unit ranges when creating a rack reservation
* [#6896](https://github.com/netbox-community/netbox/issues/6896) - Fix validation of IP address assigned as device/VM primary via NAT relation
* [#6902](https://github.com/netbox-community/netbox/issues/6902) - Populate device field when cloning device components * [#6902](https://github.com/netbox-community/netbox/issues/6902) - Populate device field when cloning device components
* [#6908](https://github.com/netbox-community/netbox/issues/6908) - Allow assignment of scope to VLAN groups upon import * [#6908](https://github.com/netbox-community/netbox/issues/6908) - Allow assignment of scope to VLAN groups upon import
* [#6909](https://github.com/netbox-community/netbox/issues/6909) - Remove extraneous `site` column from VLAN group import form * [#6909](https://github.com/netbox-community/netbox/issues/6909) - Remove extraneous `site` column from VLAN group import form
* [#6910](https://github.com/netbox-community/netbox/issues/6910) - Fix exception on invalid CSV import column name * [#6910](https://github.com/netbox-community/netbox/issues/6910) - Fix exception on invalid CSV import column name
* [#6918](https://github.com/netbox-community/netbox/issues/6918) - Fix return URL persistence when adding multiple objects sequentially
* [#6935](https://github.com/netbox-community/netbox/issues/6935) - Remove extraneous columns from inventory item and device bay tables * [#6935](https://github.com/netbox-community/netbox/issues/6935) - Remove extraneous columns from inventory item and device bay tables
* [#6936](https://github.com/netbox-community/netbox/issues/6936) - Add missing `parent` column to inventory item import form * [#6936](https://github.com/netbox-community/netbox/issues/6936) - Add missing `parent` column to inventory item import form

View File

@ -4,7 +4,8 @@ from django.utils.translation import gettext as _
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
from extras.forms import ( from extras.forms import (
AddRemoveTagsForm, CustomFieldModelBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm, CustomFieldModelFilterForm, AddRemoveTagsForm, CustomFieldModelBulkEditForm, CustomFieldModelCSVForm, CustomFieldModelForm,
CustomFieldModelFilterForm,
) )
from extras.models import Tag from extras.models import Tag
from tenancy.forms import TenancyFilterForm, TenancyForm from tenancy.forms import TenancyFilterForm, TenancyForm
@ -12,8 +13,8 @@ from tenancy.models import Tenant
from utilities.forms import ( from utilities.forms import (
add_blank_choice, BootstrapMixin, BulkEditNullBooleanSelect, ContentTypeChoiceField, CSVChoiceField, add_blank_choice, BootstrapMixin, BulkEditNullBooleanSelect, ContentTypeChoiceField, CSVChoiceField,
CSVContentTypeField, CSVModelChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField, CSVContentTypeField, CSVModelChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
ExpandableIPAddressField, NumericArrayField, ReturnURLForm, SlugField, StaticSelect, StaticSelectMultiple, ExpandableIPAddressField, NumericArrayField, SlugField, StaticSelect, StaticSelectMultiple, TagFilterField,
TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, BOOLEAN_WITH_BLANK_CHOICES,
) )
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
from .choices import * from .choices import *
@ -882,7 +883,7 @@ class IPRangeFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldModelFilte
# IP addresses # IP addresses
# #
class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldModelForm): class IPAddressForm(BootstrapMixin, TenancyForm, CustomFieldModelForm):
device = DynamicModelChoiceField( device = DynamicModelChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
required=False, required=False,

View File

@ -811,18 +811,15 @@ class IPAddress(PrimaryModel):
# Check for primary IP assignment that doesn't match the assigned device/VM # Check for primary IP assignment that doesn't match the assigned device/VM
if self.pk: if self.pk:
device = Device.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first() for cls, attr in ((Device, 'device'), (VirtualMachine, 'virtual_machine')):
if device: parent = cls.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first()
if getattr(self.assigned_object, 'device', None) != device: if parent and getattr(self.assigned_object, attr) != parent:
raise ValidationError({ # Check for a NAT relationship
'interface': f"IP address is primary for device {device} but not assigned to it!" if not self.nat_inside or getattr(self.nat_inside.assigned_object, attr) != parent:
}) raise ValidationError({
vm = VirtualMachine.objects.filter(Q(primary_ip4=self) | Q(primary_ip6=self)).first() 'interface': f"IP address is primary for {cls._meta.model_name} {parent} but "
if vm: f"not assigned to it!"
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!"
})
# Validate IP status selection # Validate IP status selection
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6: if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:

View File

@ -283,19 +283,20 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
messages.success(request, mark_safe(msg)) messages.success(request, mark_safe(msg))
if '_addanother' in request.POST: 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 the object has clone_fields, pre-populate a new instance of the form
if hasattr(obj, 'clone_fields'): if hasattr(obj, 'clone_fields'):
url = '{}?{}'.format(request.path, prepare_cloned_fields(obj)) redirect_url += f"{'&' if return_url else '?'}{prepare_cloned_fields(obj)}"
return redirect(url)
return redirect(request.get_full_path()) return redirect(redirect_url)
return_url = form.cleaned_data.get('return_url') return_url = self.get_return_url(request, obj)
if return_url is not None and is_safe_url(url=return_url, allowed_hosts=request.get_host()):
return redirect(return_url) return redirect(return_url)
else:
return redirect(self.get_return_url(request, obj))
except PermissionsViolation: except PermissionsViolation:
msg = "Object save failed due to object-level permissions violation" msg = "Object save failed due to object-level permissions violation"

View File

@ -1,4 +1,4 @@
Django==3.2.5 Django==3.2.6
django-cors-headers==3.7.0 django-cors-headers==3.7.0
django-debug-toolbar==3.2.1 django-debug-toolbar==3.2.1
django-filter==2.4.0 django-filter==2.4.0
@ -18,7 +18,7 @@ gunicorn==20.1.0
Jinja2==3.0.1 Jinja2==3.0.1
Markdown==3.3.4 Markdown==3.3.4
markdown-include==0.6.0 markdown-include==0.6.0
mkdocs-material==7.2.0 mkdocs-material==7.2.4
netaddr==0.8.0 netaddr==0.8.0
Pillow==8.3.1 Pillow==8.3.1
psycopg2-binary==2.9.1 psycopg2-binary==2.9.1