From 96eb89a469b255a209d80555d487b1cdddd6062f Mon Sep 17 00:00:00 2001 From: Arthur Date: Fri, 24 Mar 2023 08:32:52 -0700 Subject: [PATCH 01/38] 12049 fix passsword typo --- 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 7061274f1..a6abb8b73 100644 --- a/docs/configuration/system.md +++ b/docs/configuration/system.md @@ -38,7 +38,7 @@ In order to send email, NetBox needs an email server configured. The following i * `SERVER` - Hostname or IP address of the email server (use `localhost` if running locally) * `PORT` - TCP port to use for the connection (default: `25`) * `USERNAME` - Username with which to authenticate -* `PASSSWORD` - Password with which to authenticate +* `PASSWORD` - Password with which to authenticate * `USE_SSL` - Use SSL when connecting to the server (default: `False`) * `USE_TLS` - Use TLS when connecting to the server (default: `False`) * `SSL_CERTFILE` - Path to the PEM-formatted SSL certificate file (optional) From 571d33e660680951921861bf7459a33119d4866e Mon Sep 17 00:00:00 2001 From: Austin de Coup-Crank <94914780+decoupca@users.noreply.github.com> Date: Tue, 28 Mar 2023 07:44:24 -0500 Subject: [PATCH 02/38] Fixes #11977: Multiple remote authentication backends (#12012) * Add suppport for REMOTE_AUTH_BACKEND as iterable * Closes #11977: Support for multiple auth backends * Tweak list casting --------- Co-authored-by: jeremystretch --- docs/configuration/remote-authentication.md | 2 +- netbox/netbox/settings.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/configuration/remote-authentication.md b/docs/configuration/remote-authentication.md index 07adf5c6a..1fda8d0d3 100644 --- a/docs/configuration/remote-authentication.md +++ b/docs/configuration/remote-authentication.md @@ -16,7 +16,7 @@ If true, NetBox will automatically create local accounts for users authenticated Default: `'netbox.authentication.RemoteUserBackend'` -This is the Python path to the custom [Django authentication backend](https://docs.djangoproject.com/en/stable/topics/auth/customizing/) to use for external user authentication. NetBox provides two built-in backends (listed below), though custom authentication backends may also be provided by other packages or plugins. +This is the Python path to the custom [Django authentication backend](https://docs.djangoproject.com/en/stable/topics/auth/customizing/) to use for external user authentication. NetBox provides two built-in backends (listed below), though custom authentication backends may also be provided by other packages or plugins. Provide a string for a single backend, or an iterable for multiple backends, which will be attempted in the order given. * `netbox.authentication.RemoteUserBackend` * `netbox.authentication.LDAPBackend` diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 45fe32841..cf2b06a8b 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -396,8 +396,10 @@ TEMPLATES = [ ] # Set up authentication backends +if type(REMOTE_AUTH_BACKEND) not in (list, tuple): + REMOTE_AUTH_BACKEND = [REMOTE_AUTH_BACKEND] AUTHENTICATION_BACKENDS = [ - REMOTE_AUTH_BACKEND, + *REMOTE_AUTH_BACKEND, 'netbox.authentication.ObjectPermissionBackend', ] From 835af32213456a331d8450b68228cdaabdcd1e21 Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 21 Mar 2023 15:35:44 -0700 Subject: [PATCH 03/38] 12008 make export templates cloneable --- netbox/extras/models/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index e608f81b1..3b44b4b6b 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -280,7 +280,7 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged } -class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel): +class ExportTemplate(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel): content_types = models.ManyToManyField( to=ContentType, related_name='export_templates', @@ -313,6 +313,10 @@ class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel): help_text=_("Download file as attachment") ) + clone_fields = ( + 'content_types', 'template_code', 'mime_type', 'file_extension', 'as_attachment', + ) + class Meta: ordering = ('name',) From 879aabe2f9a336f5815f84ffb1eda4ba06246d1a Mon Sep 17 00:00:00 2001 From: Arthur Date: Fri, 24 Mar 2023 08:40:59 -0700 Subject: [PATCH 04/38] 12038 fix clone tag --- netbox/extras/models/tags.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/netbox/extras/models/tags.py b/netbox/extras/models/tags.py index 827d969e3..a5a202614 100644 --- a/netbox/extras/models/tags.py +++ b/netbox/extras/models/tags.py @@ -5,7 +5,7 @@ from django.utils.text import slugify from taggit.models import TagBase, GenericTaggedItemBase from netbox.models import ChangeLoggedModel -from netbox.models.features import ExportTemplatesMixin, WebhooksMixin +from netbox.models.features import CloningMixin, ExportTemplatesMixin, WebhooksMixin from utilities.choices import ColorChoices from utilities.fields import ColorField @@ -14,7 +14,7 @@ from utilities.fields import ColorField # Tags # -class Tag(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel, TagBase): +class Tag(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel, TagBase): id = models.BigAutoField( primary_key=True ) @@ -26,6 +26,10 @@ class Tag(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel, TagBase): blank=True, ) + clone_fields = ( + 'color', 'description', + ) + class Meta: ordering = ['name'] From 654e32cbbe1ca48181bc2db4d12dec69dca73ee6 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Tue, 28 Mar 2023 06:53:57 -0700 Subject: [PATCH 05/38] 11933 saved filters clone of content-types and add m2m field cloning (#12014) * 11933 saved filters clone of content-types and add m2m field cloning * Fix JSON rendering * Add content_types to CustomLink.clone() --------- Co-authored-by: jeremystretch --- netbox/extras/forms/model_forms.py | 8 ++++---- netbox/extras/models/models.py | 4 ++-- netbox/netbox/models/features.py | 7 ++++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index a21cf21e2..3fb8062e6 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -1,6 +1,7 @@ +import json + from django import forms from django.contrib.contenttypes.models import ContentType -from django.http import QueryDict from django.utils.translation import gettext as _ from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup @@ -128,11 +129,10 @@ class SavedFilterForm(BootstrapMixin, forms.ModelForm): def __init__(self, *args, initial=None, **kwargs): - # Convert any parameters delivered via initial data to a dictionary + # Convert any parameters delivered via initial data to JSON data if initial and 'parameters' in initial: if type(initial['parameters']) is str: - # TODO: Make a utility function for this - initial['parameters'] = dict(QueryDict(initial['parameters']).lists()) + initial['parameters'] = json.loads(initial['parameters']) super().__init__(*args, initial=initial, **kwargs) diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index 3b44b4b6b..bb22c9851 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -245,7 +245,7 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged ) clone_fields = ( - 'enabled', 'weight', 'group_name', 'button_class', 'new_window', + 'content_types', 'enabled', 'weight', 'group_name', 'button_class', 'new_window', ) class Meta: @@ -410,7 +410,7 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge parameters = models.JSONField() clone_fields = ( - 'enabled', 'weight', + 'content_types', 'weight', 'enabled', 'parameters', ) class Meta: diff --git a/netbox/netbox/models/features.py b/netbox/netbox/models/features.py index 62482a26f..71c1a7c5c 100644 --- a/netbox/netbox/models/features.py +++ b/netbox/netbox/models/features.py @@ -1,3 +1,4 @@ +import json from collections import defaultdict from functools import cached_property @@ -111,7 +112,11 @@ class CloningMixin(models.Model): for field_name in getattr(self, 'clone_fields', []): field = self._meta.get_field(field_name) field_value = field.value_from_object(self) - if field_value not in (None, ''): + if field_value and isinstance(field, models.ManyToManyField): + attrs[field_name] = [v.pk for v in field_value] + elif field_value and isinstance(field, models.JSONField): + attrs[field_name] = json.dumps(field_value) + elif field_value not in (None, ''): attrs[field_name] = field_value # Include tags (if applicable) From a2c7452f9010719a979c8fdc11ad97d5390b30bd Mon Sep 17 00:00:00 2001 From: Arthur Date: Mon, 27 Mar 2023 09:13:05 -0700 Subject: [PATCH 06/38] 12058 add clone to config context --- netbox/extras/models/configcontexts.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/netbox/extras/models/configcontexts.py b/netbox/extras/models/configcontexts.py index d8d3510d7..4a38115dd 100644 --- a/netbox/extras/models/configcontexts.py +++ b/netbox/extras/models/configcontexts.py @@ -5,7 +5,7 @@ from django.urls import reverse from extras.querysets import ConfigContextQuerySet from netbox.models import ChangeLoggedModel -from netbox.models.features import WebhooksMixin +from netbox.models.features import CloningMixin, WebhooksMixin from utilities.utils import deepmerge @@ -19,7 +19,7 @@ __all__ = ( # Config contexts # -class ConfigContext(WebhooksMixin, ChangeLoggedModel): +class ConfigContext(CloningMixin, WebhooksMixin, ChangeLoggedModel): """ A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B @@ -108,6 +108,12 @@ class ConfigContext(WebhooksMixin, ChangeLoggedModel): objects = ConfigContextQuerySet.as_manager() + clone_fields = ( + 'weight', 'is_active', 'regions', 'site_groups', 'sites', 'locations', 'device_types', + 'roles', 'platforms', 'cluster_types', 'cluster_groups', 'clusters', 'tenant_groups', + 'tenants', 'tags', 'data', + ) + class Meta: ordering = ['weight', 'name'] From 7d64e5bc622a371d258280384870178f92e6affd Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 28 Mar 2023 10:00:15 -0400 Subject: [PATCH 07/38] #12058: Fix initial JSON population --- netbox/extras/forms/model_forms.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py index 3fb8062e6..040882d27 100644 --- a/netbox/extras/forms/model_forms.py +++ b/netbox/extras/forms/model_forms.py @@ -254,6 +254,15 @@ class ConfigContextForm(BootstrapMixin, forms.ModelForm): 'tenants', 'tags', ) + def __init__(self, *args, initial=None, **kwargs): + + # Convert data delivered via initial data to JSON data + if initial and 'data' in initial: + if type(initial['data']) is str: + initial['data'] = json.loads(initial['data']) + + super().__init__(*args, initial=initial, **kwargs) + class ImageAttachmentForm(BootstrapMixin, forms.ModelForm): From 19787dd21d412d78f50c70258ebb3d4d5e4daa5c Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 28 Mar 2023 10:02:29 -0400 Subject: [PATCH 08/38] Update changelog --- docs/release-notes/version-3.4.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index 6ed66a61d..3f86df99d 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -5,11 +5,19 @@ ### Enhancements * [#11833](https://github.com/netbox-community/netbox/issues/11833) - Add fieldset support for custom script forms +* [#11973](https://github.com/netbox-community/netbox/issues/11833) - Use SSID for representing wireless links, if set +* [#11977](https://github.com/netbox-community/netbox/issues/11977) - Support designating multiple backends via `REMOTE_AUTH_BACKEND` config parameter +* [#11990](https://github.com/netbox-community/netbox/issues/11990) - Improve error reporting for duplicate CSV column headings ### Bug Fixes +* [#11914](https://github.com/netbox-community/netbox/issues/11914) - Include parameters when exporting saved filters +* [#11933](https://github.com/netbox-community/netbox/issues/11933) - Fix cloning of saved filters * [#11984](https://github.com/netbox-community/netbox/issues/11984) - Remove erroneous 802.3az PoE type * [#11979](https://github.com/netbox-community/netbox/issues/11979) - Correct URL for tags in route targets list +* [#12008](https://github.com/netbox-community/netbox/issues/12008) - Enable cloning of export templates +* [#12048](https://github.com/netbox-community/netbox/issues/12048) - Enable cloning of tags +* [#12058](https://github.com/netbox-community/netbox/issues/12058) - Enable cloning of config contexts --- From 87eabdbffba5d2bb2d42bc5b3464783b56ec058e Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 21 Mar 2023 17:48:29 -0700 Subject: [PATCH 09/38] 12029 add description to virtual description add --- netbox/dcim/forms/object_create.py | 2 +- netbox/templates/dcim/virtualchassis_add.html | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py index 6de193043..46f783cb7 100644 --- a/netbox/dcim/forms/object_create.py +++ b/netbox/dcim/forms/object_create.py @@ -359,7 +359,7 @@ class VirtualChassisCreateForm(NetBoxModelForm): class Meta: model = VirtualChassis fields = [ - 'name', 'domain', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', 'tags', + 'name', 'domain', 'description', 'region', 'site_group', 'site', 'rack', 'members', 'initial_position', 'tags', ] def clean(self): diff --git a/netbox/templates/dcim/virtualchassis_add.html b/netbox/templates/dcim/virtualchassis_add.html index 3c0b10826..fe68a9fc7 100644 --- a/netbox/templates/dcim/virtualchassis_add.html +++ b/netbox/templates/dcim/virtualchassis_add.html @@ -8,6 +8,7 @@ {% render_field form.name %} {% render_field form.domain %} + {% render_field form.description %} {% render_field form.tags %} From ad03061edf516d05f7d022734f4f5a4afbb5afa0 Mon Sep 17 00:00:00 2001 From: Arthur Date: Fri, 24 Mar 2023 08:14:24 -0700 Subject: [PATCH 10/38] 12038 show vc priority with placeholder --- netbox/templates/dcim/device.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index aa31db97c..896e4d8a5 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -139,7 +139,7 @@ {% if object.virtual_chassis.master == vc_member %}{% endif %} - {{ vc_member.vc_priority|default:"" }} + {{ vc_member.vc_priority|placeholder }} {% endfor %} From 1d2335d5788e6d30aedbfa02b33e31f0974826a3 Mon Sep 17 00:00:00 2001 From: Abhimanyu Saharan Date: Tue, 28 Mar 2023 19:49:18 +0530 Subject: [PATCH 11/38] Updated _schedule_at to use local time when _interval is set (#12006) * updated _schedule_at to use local time when _interval is set * updated schedule_at to use local time when interval is set --- netbox/extras/forms/reports.py | 10 +++++++--- netbox/extras/forms/scripts.py | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/netbox/extras/forms/reports.py b/netbox/extras/forms/reports.py index d2ec01006..ed7f49304 100644 --- a/netbox/extras/forms/reports.py +++ b/netbox/extras/forms/reports.py @@ -25,12 +25,16 @@ class ReportForm(BootstrapMixin, forms.Form): help_text=_("Interval at which this report is re-run (in minutes)") ) - def clean_schedule_at(self): + def clean(self): scheduled_time = self.cleaned_data['schedule_at'] - if scheduled_time and scheduled_time < timezone.now(): + if scheduled_time and scheduled_time < local_now(): raise forms.ValidationError(_('Scheduled time must be in the future.')) - return scheduled_time + # When interval is used without schedule at, raise an exception + if self.cleaned_data['interval'] and not scheduled_time: + self.cleaned_data['schedule_at'] = local_now() + + return self.cleaned_data def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/netbox/extras/forms/scripts.py b/netbox/extras/forms/scripts.py index 8216c5413..ca7398132 100644 --- a/netbox/extras/forms/scripts.py +++ b/netbox/extras/forms/scripts.py @@ -52,7 +52,7 @@ class ScriptForm(BootstrapMixin, forms.Form): # When interval is used without schedule at, raise an exception if self.cleaned_data['_interval'] and not scheduled_time: - raise forms.ValidationError(_('Scheduled time must be set when recurs is used.')) + self.cleaned_data['_schedule_at'] = local_now() return self.cleaned_data From 9995fad5135fc56b80b3c7a6d54b1da4d208cc52 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 28 Mar 2023 10:21:38 -0400 Subject: [PATCH 12/38] Update changelog for #11645, #12029, #12038 --- docs/release-notes/version-3.4.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index 3f86df99d..fa2ba157b 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -4,6 +4,7 @@ ### Enhancements +* [#11645](https://github.com/netbox-community/netbox/issues/11645) - Automatically set the scheduled time when executing reports/scripts at a recurring interval * [#11833](https://github.com/netbox-community/netbox/issues/11833) - Add fieldset support for custom script forms * [#11973](https://github.com/netbox-community/netbox/issues/11833) - Use SSID for representing wireless links, if set * [#11977](https://github.com/netbox-community/netbox/issues/11977) - Support designating multiple backends via `REMOTE_AUTH_BACKEND` config parameter @@ -16,6 +17,8 @@ * [#11984](https://github.com/netbox-community/netbox/issues/11984) - Remove erroneous 802.3az PoE type * [#11979](https://github.com/netbox-community/netbox/issues/11979) - Correct URL for tags in route targets list * [#12008](https://github.com/netbox-community/netbox/issues/12008) - Enable cloning of export templates +* [#12029](https://github.com/netbox-community/netbox/issues/12029) - Restore missing description field on virtual chassis form +* [#12038](https://github.com/netbox-community/netbox/issues/12038) - Correct display of zero values for virtual chassis member priority * [#12048](https://github.com/netbox-community/netbox/issues/12048) - Enable cloning of tags * [#12058](https://github.com/netbox-community/netbox/issues/12058) - Enable cloning of config contexts From b12551c64bcdcdb03eedec0251c80b55874e6d8f Mon Sep 17 00:00:00 2001 From: kkthxbye <400797+kkthxbye-code@users.noreply.github.com> Date: Tue, 28 Mar 2023 19:20:23 +0200 Subject: [PATCH 13/38] Fixes #11991 - Add vdcs to InterfaceImportForm and InterfaceBulkEditForm (#11996) * Add vdcs to InterfaceImportForm and InterfaceBulkEditForm * Filter vdcs queryset by device when bulk importing interfaces --- netbox/dcim/forms/bulk_edit.py | 12 ++++++++++-- netbox/dcim/forms/bulk_import.py | 19 +++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py index bd466ca48..24bd3e62d 100644 --- a/netbox/dcim/forms/bulk_edit.py +++ b/netbox/dcim/forms/bulk_edit.py @@ -1175,6 +1175,14 @@ class InterfaceBulkEditForm( }, label=_('LAG') ) + vdcs = DynamicModelMultipleChoiceField( + queryset=VirtualDeviceContext.objects.all(), + required=False, + label='Virtual Device Contexts', + query_params={ + 'device_id': '$device', + } + ) speed = forms.IntegerField( required=False, widget=SelectSpeedWidget(), @@ -1240,14 +1248,14 @@ class InterfaceBulkEditForm( fieldsets = ( (None, ('module', 'type', 'label', 'speed', 'duplex', 'description')), ('Addressing', ('vrf', 'mac_address', 'wwn')), - ('Operation', ('mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')), + ('Operation', ('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')), ('PoE', ('poe_mode', 'poe_type')), ('Related Interfaces', ('parent', 'bridge', 'lag')), ('802.1Q Switching', ('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans')), ('Wireless', ('rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width')), ) nullable_fields = ( - 'module', 'label', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'mtu', 'description', + 'module', 'label', 'parent', 'bridge', 'lag', 'speed', 'duplex', 'mac_address', 'wwn', 'vdcs', 'mtu', 'description', 'poe_mode', 'poe_type', 'mode', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'vlan_group', 'untagged_vlan', 'tagged_vlans', 'vrf', ) diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index da658d732..d29e8e250 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -11,7 +11,9 @@ from dcim.models import * from ipam.models import VRF from netbox.forms import NetBoxModelImportForm from tenancy.models import Tenant -from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField, SlugField +from utilities.forms import ( + CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField, SlugField, CSVModelMultipleChoiceField +) from virtualization.models import Cluster from wireless.choices import WirelessRoleChoices from .common import ModuleCommonForm @@ -667,6 +669,12 @@ class InterfaceImportForm(NetBoxModelImportForm): to_field_name='name', help_text=_('Parent LAG interface') ) + vdcs = CSVModelMultipleChoiceField( + queryset=VirtualDeviceContext.objects.all(), + required=False, + to_field_name='name', + help_text='VDC names separated by commas, encased with double quotes (e.g. "vdc1, vdc2, vdc3")' + ) type = CSVChoiceField( choices=InterfaceTypeChoices, help_text=_('Physical medium') @@ -706,7 +714,7 @@ class InterfaceImportForm(NetBoxModelImportForm): model = Interface fields = ( 'device', 'name', 'label', 'parent', 'bridge', 'lag', 'type', 'speed', 'duplex', 'enabled', - 'mark_connected', 'mac_address', 'wwn', 'mtu', 'mgmt_only', 'description', 'poe_mode', 'poe_type', 'mode', + 'mark_connected', 'mac_address', 'wwn', 'vdcs', 'mtu', 'mgmt_only', 'description', 'poe_mode', 'poe_type', 'mode', 'vrf', 'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'tags' ) @@ -722,6 +730,7 @@ class InterfaceImportForm(NetBoxModelImportForm): self.fields['parent'].queryset = self.fields['parent'].queryset.filter(**params) self.fields['bridge'].queryset = self.fields['bridge'].queryset.filter(**params) self.fields['lag'].queryset = self.fields['lag'].queryset.filter(**params) + self.fields['vdcs'].queryset = self.fields['vdcs'].queryset.filter(**params) def clean_enabled(self): # Make sure enabled is True when it's not included in the uploaded data @@ -730,6 +739,12 @@ class InterfaceImportForm(NetBoxModelImportForm): else: return self.cleaned_data['enabled'] + def clean_vdcs(self): + for vdc in self.cleaned_data['vdcs']: + if vdc.device != self.cleaned_data['device']: + raise forms.ValidationError(f"VDC {vdc} is not assigned to device {self.cleaned_data['device']}") + return self.cleaned_data['vdcs'] + class FrontPortImportForm(NetBoxModelImportForm): device = CSVModelChoiceField( From d3c5f1e7445420af74580efc60df597848918566 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Tue, 28 Mar 2023 13:46:43 -0400 Subject: [PATCH 14/38] Release v3.4.7 --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 2 +- base_requirements.txt | 3 ++- docs/release-notes/version-3.4.md | 3 ++- netbox/netbox/settings.py | 2 +- requirements.txt | 12 ++++++------ 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 51c0a5a0d..54f4f7eae 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.4.6 + placeholder: v3.4.7 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 7c6b4e151..c9bc56ffc 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.4.6 + placeholder: v3.4.7 validations: required: true - type: dropdown diff --git a/base_requirements.txt b/base_requirements.txt index 7292c676b..f3303e6e3 100644 --- a/base_requirements.txt +++ b/base_requirements.txt @@ -121,7 +121,8 @@ social-auth-core # Django app for social-auth-core # https://github.com/python-social-auth/social-app-django -social-auth-app-django +# See https://github.com/python-social-auth/social-app-django/issues/429 +social-auth-app-django==5.0.0 # SVG image rendering (used for rack elevations) # https://github.com/mozman/svgwrite diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index fa2ba157b..c14acca66 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -1,6 +1,6 @@ # NetBox v3.4 -## v3.4.7 (FUTURE) +## v3.4.7 (2023-03-28) ### Enhancements @@ -9,6 +9,7 @@ * [#11973](https://github.com/netbox-community/netbox/issues/11833) - Use SSID for representing wireless links, if set * [#11977](https://github.com/netbox-community/netbox/issues/11977) - Support designating multiple backends via `REMOTE_AUTH_BACKEND` config parameter * [#11990](https://github.com/netbox-community/netbox/issues/11990) - Improve error reporting for duplicate CSV column headings +* [#11991](https://github.com/netbox-community/netbox/issues/11991) - Enable VDC assignment during bulk import/edit of interfaces ### Bug Fixes diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index cf2b06a8b..17414d4e1 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -24,7 +24,7 @@ from netbox.constants import RQ_QUEUE_DEFAULT, RQ_QUEUE_HIGH, RQ_QUEUE_LOW # Environment setup # -VERSION = '3.4.7-dev' +VERSION = '3.4.7' # Hostname HOSTNAME = platform.node() diff --git a/requirements.txt b/requirements.txt index 92f60335a..5844f62b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ bleach==5.0.1 Django==4.1.7 django-cors-headers==3.14.0 django-debug-toolbar==3.8.1 -django-filter==22.1 +django-filter==23.1 django-graphiql-debug-toolbar==0.2.0 django-mptt==0.14 django-pglocks==1.0.4 @@ -19,18 +19,18 @@ graphene-django==3.0.0 gunicorn==20.1.0 Jinja2==3.1.2 Markdown==3.3.7 -mkdocs-material==9.1.2 +mkdocs-material==9.1.4 mkdocstrings[python-legacy]==0.20.0 netaddr==0.8.0 Pillow==9.4.0 psycopg2-binary==2.9.5 PyYAML==6.0 -sentry-sdk==1.16.0 +sentry-sdk==1.18.0 social-auth-app-django==5.0.0 -social-auth-core[openidconnect]==4.3.0 +social-auth-core[openidconnect]==4.4.0 svgwrite==1.4.3 -tablib==3.3.0 -tzdata==2022.7 +tablib==3.4.0 +tzdata==2023.2 # Workaround for #7401 jsonschema==3.2.0 From f67deb0deaedefa078286610dff124e5e7945442 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 13 Mar 2023 11:59:57 -0400 Subject: [PATCH 15/38] PRVB --- docs/release-notes/version-3.4.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.4.md b/docs/release-notes/version-3.4.md index 43f4dab5e..d754123c6 100644 --- a/docs/release-notes/version-3.4.md +++ b/docs/release-notes/version-3.4.md @@ -1,5 +1,9 @@ # NetBox v3.4 +## v3.4.7 (FUTURE) + +--- + ## v3.4.6 (2023-03-13) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index c87303649..45fe32841 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -24,7 +24,7 @@ from netbox.constants import RQ_QUEUE_DEFAULT, RQ_QUEUE_HIGH, RQ_QUEUE_LOW # Environment setup # -VERSION = '3.4.6' +VERSION = '3.4.7-dev' # Hostname HOSTNAME = platform.node() From 371764fecd837a328e0be3ed740f7231fb90772d Mon Sep 17 00:00:00 2001 From: Ryan Merolle Date: Tue, 14 Mar 2023 15:50:49 -0400 Subject: [PATCH 16/38] Add fieldsets functionality to scripts to allow for form field groupings (#11880) * update script template * update docs * introduce default_fieldset * correct custom script docs * default to use fieldsets in scripts * update scripts docs for new behavior * Misc cleanup --------- Co-authored-by: jeremystretch --- docs/customization/custom-scripts.md | 19 +++++++++++++++++-- netbox/extras/scripts.py | 12 ++++++++++++ netbox/templates/extras/script.html | 26 ++++++++++++++++++++++---- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/docs/customization/custom-scripts.md b/docs/customization/custom-scripts.md index af1e9b5b6..ccbe50885 100644 --- a/docs/customization/custom-scripts.md +++ b/docs/customization/custom-scripts.md @@ -79,7 +79,22 @@ A human-friendly description of what your script does. ### `field_order` -By default, script variables will be ordered in the form as they are defined in the script. `field_order` may be defined as an iterable of field names to determine the order in which variables are rendered. Any fields not included in this iterable be listed last. +By default, script variables will be ordered in the form as they are defined in the script. `field_order` may be defined as an iterable of field names to determine the order in which variables are rendered within a default "Script Data" group. Any fields not included in this iterable be listed last. If `fieldsets` is defined, `field_order` will be ignored. A fieldset group for "Script Execution Parameters" will be added to the end of the form by default for the user. + +### `fieldsets` + +`fieldsets` may be defined as an iterable of field groups and their field names to determine the order in which variables are group and rendered. Any fields not included in this iterable will not be displayed in the form. If `fieldsets` is defined, `field_order` will be ignored. A fieldset group for "Script Execution Parameters" will be added to the end of the fieldsets by default for the user. + +An example fieldset definition is provided below: + +```python +class MyScript(Script): + class Meta: + fieldsets = ( + ('First group', ('field1', 'field2', 'field3')), + ('Second group', ('field4', 'field5')), + ) +``` ### `commit_default` @@ -302,7 +317,7 @@ Optionally `schedule_at` can be passed in the form data with a datetime string t Scripts can be run on the CLI by invoking the management command: ``` -python3 manage.py runscript [--commit] [--loglevel {debug,info,warning,error,critical}] [--data ""] .