From 695ad47fe9e4f5fa3193fe4f08afd985d6eac4d6 Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 19 Sep 2022 10:46:16 -0700 Subject: [PATCH 1/7] 10408 add error message if already exists --- netbox/netbox/views/generic/object_views.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index a56a832b6..85604cd8f 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -3,7 +3,7 @@ from copy import deepcopy from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist -from django.db import transaction +from django.db import transaction, IntegrityError from django.db.models import ProtectedError from django.forms.widgets import HiddenInput from django.shortcuts import redirect, render @@ -421,7 +421,11 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): return redirect(return_url) - except (AbortRequest, PermissionsViolation) as e: + except IntegrityError: + form.add_error(None, f"{obj} already exists") + clear_webhooks.send(sender=self) + + except (IntegrityError, AbortRequest, PermissionsViolation) as e: logger.debug(e.message) form.add_error(None, e.message) clear_webhooks.send(sender=self) From 7735634649933e1c64d410a4fbc69f6bc8c975e6 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 22 Sep 2022 10:34:37 -0700 Subject: [PATCH 2/7] 10435 check if vm.cluster in qs --- netbox/ipam/querysets.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/netbox/ipam/querysets.py b/netbox/ipam/querysets.py index 7edac2eff..b64ae04b8 100644 --- a/netbox/ipam/querysets.py +++ b/netbox/ipam/querysets.py @@ -81,30 +81,31 @@ class VLANQuerySet(RestrictedQuerySet): # Find all relevant VLANGroups q = Q() - if vm.cluster.site: - if vm.cluster.site.region: + if vm.cluster: + if vm.cluster.site: + if vm.cluster.site.region: + q |= Q( + scope_type=ContentType.objects.get_by_natural_key('dcim', 'region'), + scope_id__in=vm.cluster.site.region.get_ancestors(include_self=True) + ) + if vm.cluster.site.group: + q |= Q( + scope_type=ContentType.objects.get_by_natural_key('dcim', 'sitegroup'), + scope_id__in=vm.cluster.site.group.get_ancestors(include_self=True) + ) q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'region'), - scope_id__in=vm.cluster.site.region.get_ancestors(include_self=True) + scope_type=ContentType.objects.get_by_natural_key('dcim', 'site'), + scope_id=vm.cluster.site_id ) - if vm.cluster.site.group: + if vm.cluster.group: q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'sitegroup'), - scope_id__in=vm.cluster.site.group.get_ancestors(include_self=True) + scope_type=ContentType.objects.get_by_natural_key('virtualization', 'clustergroup'), + scope_id=vm.cluster.group_id ) q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'site'), - scope_id=vm.cluster.site_id + scope_type=ContentType.objects.get_by_natural_key('virtualization', 'cluster'), + scope_id=vm.cluster_id ) - if vm.cluster.group: - q |= Q( - scope_type=ContentType.objects.get_by_natural_key('virtualization', 'clustergroup'), - scope_id=vm.cluster.group_id - ) - q |= Q( - scope_type=ContentType.objects.get_by_natural_key('virtualization', 'cluster'), - scope_id=vm.cluster_id - ) vlan_groups = VLANGroup.objects.filter(q) # Return all applicable VLANs @@ -113,7 +114,7 @@ class VLANQuerySet(RestrictedQuerySet): Q(group__scope_id__isnull=True, site__isnull=True) | # Global group VLANs Q(group__isnull=True, site__isnull=True) # Global VLANs ) - if vm.cluster.site: + if vm.cluster and vm.cluster.site: q |= Q(site=vm.cluster.site) return self.filter(q) From c97d2d4fe9c9fdc4f348fc03facdae79c7f2894b Mon Sep 17 00:00:00 2001 From: "Artem I. Kotik" Date: Sat, 24 Sep 2022 15:49:23 +0400 Subject: [PATCH 3/7] Add widget for Airflow field in DeviceTypeForm --- netbox/dcim/forms/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/netbox/dcim/forms/models.py b/netbox/dcim/forms/models.py index 5728e7f2d..b33023ece 100644 --- a/netbox/dcim/forms/models.py +++ b/netbox/dcim/forms/models.py @@ -373,6 +373,7 @@ class DeviceTypeForm(NetBoxModelForm): 'front_image', 'rear_image', 'comments', 'tags', ] widgets = { + 'airflow': StaticSelect(), 'subdevice_role': StaticSelect(), 'front_image': ClearableFileInput(attrs={ 'accept': DEVICETYPE_IMAGE_FORMATS From 39129ecedfb5755ac1c1c827abf60f5904670d80 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Mon, 26 Sep 2022 06:17:02 -0700 Subject: [PATCH 4/7] 10407 fix documentation link to requests (#10409) * 10407 fix documentation link to requests * Append page heading to URL Co-authored-by: jeremystretch --- docs/configuration/system.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration/system.md b/docs/configuration/system.md index 21607e566..93f8fa902 100644 --- a/docs/configuration/system.md +++ b/docs/configuration/system.md @@ -58,7 +58,7 @@ Email is sent from NetBox only for critical events or if configured for [logging Default: None -A dictionary of HTTP proxies to use for outbound requests originating from NetBox (e.g. when sending webhook requests). Proxies should be specified by schema (HTTP and HTTPS) as per the [Python requests library documentation](https://2.python-requests.org/en/master/user/advanced/). For example: +A dictionary of HTTP proxies to use for outbound requests originating from NetBox (e.g. when sending webhook requests). Proxies should be specified by schema (HTTP and HTTPS) as per the [Python requests library documentation](https://requests.readthedocs.io/en/latest/user/advanced/#proxies). For example: ```python HTTP_PROXIES = { From 3ad337dd15b569a644e7f0a1a22fed4970ccf295 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 26 Sep 2022 10:08:54 -0400 Subject: [PATCH 5/7] Filter VLANs and VLANGroups by site or cluster site for VM --- netbox/ipam/querysets.py | 41 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/netbox/ipam/querysets.py b/netbox/ipam/querysets.py index b64ae04b8..9f4463f61 100644 --- a/netbox/ipam/querysets.py +++ b/netbox/ipam/querysets.py @@ -81,31 +81,34 @@ class VLANQuerySet(RestrictedQuerySet): # Find all relevant VLANGroups q = Q() + site = vm.site or vm.cluster.site if vm.cluster: - if vm.cluster.site: - if vm.cluster.site.region: - q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'region'), - scope_id__in=vm.cluster.site.region.get_ancestors(include_self=True) - ) - if vm.cluster.site.group: - q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'sitegroup'), - scope_id__in=vm.cluster.site.group.get_ancestors(include_self=True) - ) - q |= Q( - scope_type=ContentType.objects.get_by_natural_key('dcim', 'site'), - scope_id=vm.cluster.site_id - ) + # Add VLANGroups scoped to the assigned cluster (or its group) + q |= Q( + scope_type=ContentType.objects.get_by_natural_key('virtualization', 'cluster'), + scope_id=vm.cluster_id + ) if vm.cluster.group: q |= Q( scope_type=ContentType.objects.get_by_natural_key('virtualization', 'clustergroup'), scope_id=vm.cluster.group_id ) + if site: + # Add VLANGroups scoped to the assigned site (or its group or region) q |= Q( - scope_type=ContentType.objects.get_by_natural_key('virtualization', 'cluster'), - scope_id=vm.cluster_id + scope_type=ContentType.objects.get_by_natural_key('dcim', 'site'), + scope_id=site.pk ) + if site.region: + q |= Q( + scope_type=ContentType.objects.get_by_natural_key('dcim', 'region'), + scope_id__in=site.region.get_ancestors(include_self=True) + ) + if site.group: + q |= Q( + scope_type=ContentType.objects.get_by_natural_key('dcim', 'sitegroup'), + scope_id__in=site.group.get_ancestors(include_self=True) + ) vlan_groups = VLANGroup.objects.filter(q) # Return all applicable VLANs @@ -114,7 +117,7 @@ class VLANQuerySet(RestrictedQuerySet): Q(group__scope_id__isnull=True, site__isnull=True) | # Global group VLANs Q(group__isnull=True, site__isnull=True) # Global VLANs ) - if vm.cluster and vm.cluster.site: - q |= Q(site=vm.cluster.site) + if site: + q |= Q(site=site) return self.filter(q) From fd89ef04b6eac975bf7acf2cbada4810442c0bf3 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 26 Sep 2022 10:24:40 -0400 Subject: [PATCH 6/7] Revert "10408 add error message if already exists" --- netbox/netbox/views/generic/object_views.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/netbox/netbox/views/generic/object_views.py b/netbox/netbox/views/generic/object_views.py index 85604cd8f..a56a832b6 100644 --- a/netbox/netbox/views/generic/object_views.py +++ b/netbox/netbox/views/generic/object_views.py @@ -3,7 +3,7 @@ from copy import deepcopy from django.contrib import messages from django.core.exceptions import ObjectDoesNotExist -from django.db import transaction, IntegrityError +from django.db import transaction from django.db.models import ProtectedError from django.forms.widgets import HiddenInput from django.shortcuts import redirect, render @@ -421,11 +421,7 @@ class ObjectEditView(GetReturnURLMixin, BaseObjectView): return redirect(return_url) - except IntegrityError: - form.add_error(None, f"{obj} already exists") - clear_webhooks.send(sender=self) - - except (IntegrityError, AbortRequest, PermissionsViolation) as e: + except (AbortRequest, PermissionsViolation) as e: logger.debug(e.message) form.add_error(None, e.message) clear_webhooks.send(sender=self) From 96784640e371d12c0dcd97d15ceae4a45663f8c0 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 26 Sep 2022 10:27:35 -0400 Subject: [PATCH 7/7] Changelog for #10435, #10439 --- docs/release-notes/version-3.3.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 71f5605f9..2955e17d5 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -2,13 +2,17 @@ ## v3.3.5 (FUTURE) +### Bug Fixes + +* [#9497](https://github.com/netbox-community/netbox/issues/9497) - Adjust non-racked device filter on site and location detailed view +* [#10435](https://github.com/netbox-community/netbox/issues/10435) - Fix exception when filtering VLANs by virtual machine with no cluster assigned +* [#10439](https://github.com/netbox-community/netbox/issues/10439) - Fix form widget styling for DeviceType airflow field + --- ## v3.3.4 (2022-09-16) ### Bug Fixes - -* [#9497](https://github.com/netbox-community/netbox/issues/9497) - Adjust non-racked device filter on site and location detailed view * [#10383](https://github.com/netbox-community/netbox/issues/10383) - Fix assignment of component templates to module types via web UI * [#10387](https://github.com/netbox-community/netbox/issues/10387) - Fix `MultiValueDictKeyError` exception when editing a device interface