Skip to content

Commit

Permalink
Merge pull request #17478 from netbox-community/develop
Browse files Browse the repository at this point in the history
Release v4.1.1
  • Loading branch information
jeremystretch authored Sep 12, 2024
2 parents 7bc0d34 + 15a106b commit 0e34fba
Show file tree
Hide file tree
Showing 118 changed files with 56,642 additions and 133,462 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v4.1.0
placeholder: v4.1.1
validations:
required: true
- type: dropdown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ body:
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v4.1.0
placeholder: v4.1.1
validations:
required: true
- type: dropdown
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions .github/workflows/close-stale-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ jobs:
This PR has been automatically closed due to lack of activity.
days-before-pr-stale: 15
days-before-pr-close: 15
exempt-pr-labels: 'status: blocked'
stale-pr-label: 'pending closure'
stale-pr-message: >
This PR has been automatically marked as stale because it has not had
Expand Down
4 changes: 0 additions & 4 deletions base_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ Jinja2
# https://python-markdown.github.io/changelog/
Markdown

# File inclusion plugin for Python-Markdown
# https://github.com/cmacmackin/markdown-include
markdown-include

# MkDocs Material theme (for documentation build)
# https://squidfunk.github.io/mkdocs-material/changelog/
mkdocs-material
Expand Down
2 changes: 1 addition & 1 deletion contrib/apache.conf
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
Alias /static /opt/netbox/netbox/static

<Directory /opt/netbox/netbox/static>
Options Indexes FollowSymLinks MultiViews
Options FollowSymLinks MultiViews
AllowOverride None
Require all granted
</Directory>
Expand Down
18 changes: 18 additions & 0 deletions contrib/generated_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
"nema-l15-60p",
"nema-l21-20p",
"nema-l21-30p",
"nema-l22-20p",
"nema-l22-30p",
"cs6361c",
"cs6365c",
Expand Down Expand Up @@ -262,6 +263,7 @@
"nema-l15-60r",
"nema-l21-20r",
"nema-l21-30r",
"nema-l22-20r",
"nema-l22-30r",
"CS6360C",
"CS6364C",
Expand Down Expand Up @@ -518,6 +520,14 @@
"urm-p4",
"urm-p8",
"splice",
"usb-a",
"usb-b",
"usb-c",
"usb-mini-a",
"usb-mini-b",
"usb-micro-a",
"usb-micro-b",
"usb-micro-ab",
"other"
]
}
Expand Down Expand Up @@ -575,6 +585,14 @@
"urm-p4",
"urm-p8",
"splice",
"usb-a",
"usb-b",
"usb-c",
"usb-mini-a",
"usb-mini-b",
"usb-micro-a",
"usb-micro-b",
"usb-micro-ab",
"other"
]
}
Expand Down
3 changes: 3 additions & 0 deletions docs/customization/custom-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ They can also be used as a mechanism for validating the integrity of data within

Custom scripts are Python code which exists outside the NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're completely custom, there is no inherent limitation on what a script can accomplish.

!!! danger "Only install trusted scripts"
Custom scripts have unrestricted access to change anything in the databse and are inherently unsafe and should only be installed and run from trusted sources. You should also review and set permissions for who can run scripts if the script can modify any data.

## Writing Custom Scripts

All custom scripts must inherit from the `extras.scripts.Script` base class. This class provides the functionality necessary to generate forms and log activity.
Expand Down
4 changes: 4 additions & 0 deletions docs/development/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ mkdocs serve

Follow these instructions to perform a new installation of NetBox in a temporary environment. This process must not be automated: The goal of this step is to catch any errors or omissions in the documentation, and ensure that it is kept up-to-date for each release. Make any necessary changes to the documentation before proceeding with the release.

### Test Upgrade Paths

Upgrading from a previous version typically involves database migrations, which must work without errors. Supported upgrade paths include from one minor version to another within the same major version (i.e. 4.0 to 4.1), as well as from the latest patch version of the previous minor version (i.e. 3.7 to 4.0 or to 4.1). Prior to release, test all these supported paths by loading demo data from the source version and performing a `./manage.py migrate`.

### Merge the Release Branch

Submit a pull request to merge the `feature` branch into the `develop` branch in preparation for its release. Once it has been merged, continue with the section for patch releases below.
Expand Down
26 changes: 26 additions & 0 deletions docs/release-notes/version-4.1.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# NetBox v4.1

## v4.1.1 (2024-09-12)

### Enhancements

* [#16926](https://github.com/netbox-community/netbox/issues/16926) - Add USB front & rear port types
* [#17347](https://github.com/netbox-community/netbox/issues/17347) - Add NEMA L22-20 power port & outlet types

### Bug Fixes

* [#17066](https://github.com/netbox-community/netbox/issues/17066) - Fix OpenAPI schema definition for custom scripts REST API endpoint
* [#17332](https://github.com/netbox-community/netbox/issues/17332) - Restore pagination for object list dashboard widgets
* [#17333](https://github.com/netbox-community/netbox/issues/17333) - Avoid prefetching all jobs when retrieving custom scripts via the REST API
* [#17353](https://github.com/netbox-community/netbox/issues/17353) - Fix styling of map buttons under site and device views
* [#17354](https://github.com/netbox-community/netbox/issues/17354) - Prevent object & multi-object custom fields from breaking bulk import forms
* [#17362](https://github.com/netbox-community/netbox/issues/17362) - Remove duplicate prefixes & IP addresses returned by the `present_in_vrf` query filter
* [#17364](https://github.com/netbox-community/netbox/issues/17364) - Fix rendering of Markdown tables inside object list dashboard widgets
* [#17387](https://github.com/netbox-community/netbox/issues/17387) - Fix display of the changelog tab for users with sufficient permission
* [#17410](https://github.com/netbox-community/netbox/issues/17410) - Enable debug toolbar middleware for `strawberry-django` only when `DEBUG` is true
* [#17414](https://github.com/netbox-community/netbox/issues/17414) - Fix support for declaring individual VLAN IDs within a VLAN group
* [#17431](https://github.com/netbox-community/netbox/issues/17431) - Fix database migration error when upgrading to v4.1 from v3.7 or earlier
* [#17437](https://github.com/netbox-community/netbox/issues/17437) - Fix exception when specifying a bridge relationship on an interface template
* [#17444](https://github.com/netbox-community/netbox/issues/17444) - Custom script fails to execute when triggered by an event rule
* [#17457](https://github.com/netbox-community/netbox/issues/17457) - GraphQL `service_list` filter should not require a port number

---

## v4.1.0 (2024-09-03)

### Breaking Changes
Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/api/serializers_/nested.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class NestedInterfaceTemplateSerializer(WritableNestedSerializer):

class Meta:
model = models.InterfaceTemplate
fields = ['id', 'url', 'display_url', 'display', 'name']
fields = ['id', 'url', 'display', 'name']


class NestedDeviceBaySerializer(WritableNestedSerializer):
Expand Down
27 changes: 27 additions & 0 deletions netbox/dcim/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ class PowerPortTypeChoices(ChoiceSet):
TYPE_NEMA_L1560P = 'nema-l15-60p'
TYPE_NEMA_L2120P = 'nema-l21-20p'
TYPE_NEMA_L2130P = 'nema-l21-30p'
TYPE_NEMA_L2220P = 'nema-l22-20p'
TYPE_NEMA_L2230P = 'nema-l22-30p'
# California style
TYPE_CS6361C = 'cs6361c'
Expand Down Expand Up @@ -517,6 +518,7 @@ class PowerPortTypeChoices(ChoiceSet):
(TYPE_NEMA_L1560P, 'NEMA L15-60P'),
(TYPE_NEMA_L2120P, 'NEMA L21-20P'),
(TYPE_NEMA_L2130P, 'NEMA L21-30P'),
(TYPE_NEMA_L2220P, 'NEMA L22-20P'),
(TYPE_NEMA_L2230P, 'NEMA L22-30P'),
)),
(_('California Style'), (
Expand Down Expand Up @@ -649,6 +651,7 @@ class PowerOutletTypeChoices(ChoiceSet):
TYPE_NEMA_L1560R = 'nema-l15-60r'
TYPE_NEMA_L2120R = 'nema-l21-20r'
TYPE_NEMA_L2130R = 'nema-l21-30r'
TYPE_NEMA_L2220R = 'nema-l22-20r'
TYPE_NEMA_L2230R = 'nema-l22-30r'
# California style
TYPE_CS6360C = 'CS6360C'
Expand Down Expand Up @@ -763,6 +766,7 @@ class PowerOutletTypeChoices(ChoiceSet):
(TYPE_NEMA_L1560R, 'NEMA L15-60R'),
(TYPE_NEMA_L2120R, 'NEMA L21-20R'),
(TYPE_NEMA_L2130R, 'NEMA L21-30R'),
(TYPE_NEMA_L2220R, 'NEMA L22-20R'),
(TYPE_NEMA_L2230R, 'NEMA L22-30R'),
)),
(_('California Style'), (
Expand Down Expand Up @@ -1347,6 +1351,14 @@ class PortTypeChoices(ChoiceSet):
TYPE_URM_P2 = 'urm-p2'
TYPE_URM_P4 = 'urm-p4'
TYPE_URM_P8 = 'urm-p8'
TYPE_USB_A = 'usb-a'
TYPE_USB_B = 'usb-b'
TYPE_USB_C = 'usb-c'
TYPE_USB_MINI_A = 'usb-mini-a'
TYPE_USB_MINI_B = 'usb-mini-b'
TYPE_USB_MICRO_A = 'usb-micro-a'
TYPE_USB_MICRO_B = 'usb-micro-b'
TYPE_USB_MICRO_AB = 'usb-micro-ab'
TYPE_OTHER = 'other'

CHOICES = (
Expand Down Expand Up @@ -1406,6 +1418,19 @@ class PortTypeChoices(ChoiceSet):
(TYPE_SPLICE, 'Splice'),
),
),
(
_('USB'),
(
(TYPE_USB_A, 'USB Type A'),
(TYPE_USB_B, 'USB Type B'),
(TYPE_USB_C, 'USB Type C'),
(TYPE_USB_MINI_A, 'USB Mini A'),
(TYPE_USB_MINI_B, 'USB Mini B'),
(TYPE_USB_MICRO_A, 'USB Micro A'),
(TYPE_USB_MICRO_B, 'USB Micro B'),
(TYPE_USB_MICRO_AB, 'USB Micro AB'),
),
),
(
_('Other'),
(
Expand Down Expand Up @@ -1444,6 +1469,7 @@ class CableTypeChoices(ChoiceSet):
TYPE_SMF_OS2 = 'smf-os2'
TYPE_AOC = 'aoc'
TYPE_POWER = 'power'
TYPE_USB = 'usb'

CHOICES = (
(
Expand Down Expand Up @@ -1476,6 +1502,7 @@ class CableTypeChoices(ChoiceSet):
(TYPE_AOC, 'Active Optical Cabling (AOC)'),
),
),
(TYPE_USB, _('USB')),
(TYPE_POWER, _('Power')),
)

Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/forms/model_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -975,8 +975,8 @@ class InterfaceTemplateForm(ModularComponentTemplateForm):
queryset=InterfaceTemplate.objects.all(),
required=False,
query_params={
'devicetype_id': '$device_type',
'moduletype_id': '$module_type',
'device_type_id': '$device_type',
'module_type_id': '$module_type',
}
)

Expand Down
7 changes: 6 additions & 1 deletion netbox/extras/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.shortcuts import get_object_or_404
from django.utils.module_loading import import_string
from django_rq.queues import get_connection
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
Expand Down Expand Up @@ -229,9 +230,13 @@ def render(self, request, pk):
# Scripts
#

@extend_schema_view(
update=extend_schema(request=serializers.ScriptInputSerializer),
partial_update=extend_schema(request=serializers.ScriptInputSerializer),
)
class ScriptViewSet(ModelViewSet):
permission_classes = [IsAuthenticatedOrLoginNotRequired]
queryset = Script.objects.prefetch_related('jobs')
queryset = Script.objects.all()
serializer_class = serializers.ScriptSerializer
filterset_class = filtersets.ScriptFilterSet

Expand Down
30 changes: 18 additions & 12 deletions netbox/extras/models/customfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -525,23 +525,29 @@ def to_form_field(self, set_initial=True, enforce_required=True, enforce_visibil
elif self.type == CustomFieldTypeChoices.TYPE_OBJECT:
model = self.related_object_type.model_class()
field_class = CSVModelChoiceField if for_csv_import else DynamicModelChoiceField
field = field_class(
queryset=model.objects.all(),
required=required,
initial=initial,
query_params=self.related_object_filter
)
kwargs = {
'queryset': model.objects.all(),
'required': required,
'initial': initial,
}
if not for_csv_import:
kwargs['query_params'] = self.related_object_filter

field = field_class(**kwargs)

# Multiple objects
elif self.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT:
model = self.related_object_type.model_class()
field_class = CSVModelMultipleChoiceField if for_csv_import else DynamicModelMultipleChoiceField
field = field_class(
queryset=model.objects.all(),
required=required,
initial=initial,
query_params=self.related_object_filter
)
kwargs = {
'queryset': model.objects.all(),
'required': required,
'initial': initial,
}
if not for_csv_import:
kwargs['query_params'] = self.related_object_filter

field = field_class(**kwargs)

# Text
else:
Expand Down
4 changes: 2 additions & 2 deletions netbox/ipam/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ def filter_present_in_vrf(self, queryset, name, vrf):
return queryset.filter(
Q(vrf=vrf) |
Q(vrf__export_targets__in=vrf.import_targets.all())
)
).distinct()


class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
Expand Down Expand Up @@ -738,7 +738,7 @@ def filter_present_in_vrf(self, queryset, name, vrf):
return queryset.filter(
Q(vrf=vrf) |
Q(vrf__export_targets__in=vrf.import_targets.all())
)
).distinct()

def filter_device(self, queryset, name, value):
devices = Device.objects.filter(**{'{}__in'.format(name): value})
Expand Down
2 changes: 1 addition & 1 deletion netbox/ipam/models/vlans.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def clean(self):
if self.vid_ranges and check_ranges_overlap(self.vid_ranges):
raise ValidationError({'vid_ranges': _("Ranges cannot overlap.")})
for vid_range in self.vid_ranges:
if vid_range.lower >= vid_range.upper:
if vid_range.lower > vid_range.upper:
raise ValidationError({
'vid_ranges': _(
"Maximum child VID must be greater than or equal to minimum child VID ({value})"
Expand Down
14 changes: 14 additions & 0 deletions netbox/ipam/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -543,3 +543,17 @@ def test_vid_validation(self):

vlan = VLAN(vid=109, name='VLAN 109', group=vlangroup)
vlan.full_clean()

def test_overlapping_vlan(self):
vlangroup = VLANGroup(
name='VLAN Group 1',
slug='vlan-group-1',
vid_ranges=string_to_ranges('2-4,3-5'),
)
with self.assertRaises(ValidationError):
vlangroup.full_clean()

# make sure single vlan range works
vlangroup.vid_ranges = string_to_ranges('2-2')
vlangroup.full_clean()
vlangroup.save()
2 changes: 1 addition & 1 deletion netbox/netbox/graphql/filter_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def map_strawberry_type(field):
pass
elif isinstance(field, NumericArrayFilter):
should_create_function = True
attr_type = int
attr_type = int | None
elif isinstance(field, TreeNodeMultipleChoiceFilter):
should_create_function = True
attr_type = List[str] | None
Expand Down
3 changes: 2 additions & 1 deletion netbox/netbox/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ def enqueue(cls, *args, **kwargs):
This method is a wrapper of `Job.enqueue()` using `handle()` as function callback. See its documentation for
parameters.
"""
return Job.enqueue(cls.handle, name=cls.name, *args, **kwargs)
name = kwargs.pop('name', None) or cls.name
return Job.enqueue(cls.handle, name=name, *args, **kwargs)

@classmethod
@advisory_lock(ADVISORY_LOCK_KEYS['job-schedules'])
Expand Down
8 changes: 7 additions & 1 deletion netbox/netbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,6 @@ def _setting(name, default=None):

# Middleware
MIDDLEWARE = [
"strawberry_django.middlewares.debug_toolbar.DebugToolbarMiddleware",
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
Expand All @@ -431,6 +430,13 @@ def _setting(name, default=None):
'netbox.middleware.CoreMiddleware',
'netbox.middleware.MaintenanceModeMiddleware',
]

if DEBUG:
MIDDLEWARE = [
"strawberry_django.middlewares.debug_toolbar.DebugToolbarMiddleware",
*MIDDLEWARE,
]

if METRICS_ENABLED:
# If metrics are enabled, add the before & after Prometheus middleware
MIDDLEWARE = [
Expand Down
Loading

0 comments on commit 0e34fba

Please sign in to comment.