Compare commits

...

10 Commits

Author SHA1 Message Date
github-actions
1e297d55ee Update source translation strings
Some checks are pending
CI / build (20.x, 3.12) (push) Waiting to run
CI / build (20.x, 3.13) (push) Waiting to run
CI / build (20.x, 3.14) (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2026-01-16 05:04:49 +00:00
bctiemann
fdb987ef91 Merge pull request #21183 from netbox-community/21178-change-rack-dimensions-display-to-be-more-consistent
Fixes #21178: Add spacing in mounting depth format string
2026-01-15 17:48:39 -05:00
bctiemann
b5a23db43c Merge pull request #21164 from netbox-community/21118-site
fix performance regression for Site save, use bulk_update for cached fields
2026-01-15 17:48:01 -05:00
bctiemann
366b69aff7 Merge pull request #21143 from netbox-community/21050-device-oob-ip-may-become-orphaned
Fixes #21050: Prevent reassignment of OOB IPs
2026-01-15 17:47:00 -05:00
bctiemann
c3e8c5e69c Merge pull request #21100 from netbox-community/21097-graphql-id-lookups
Fixes #21097: Fix comparison lookups for ID filters in GraphQL API
2026-01-15 17:44:22 -05:00
adionit7
b55f36469d Update CodeQL Action from v3 to v4
Some checks failed
CI / build (20.x, 3.12) (push) Has been cancelled
CI / build (20.x, 3.13) (push) Has been cancelled
CI / build (20.x, 3.14) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
- Update github/codeql-action/init from @v3 to @v4
- Update github/codeql-action/analyze from @v3 to @v4

Fixes #21156
2026-01-15 16:46:25 -05:00
Martin Hauser
7fded2fd87 fix(dcim): Add spacing in mounting depth format string
Corrects the format string for mounting depth to include a space
between the value and the unit (`mm`) for consistency with other
measurements.

Fixes #21178
2026-01-15 18:52:25 +01:00
Arthur
8cbfe94fba fix performance regression for Site save, use bulk_update for cached fields 2026-01-14 16:30:40 -08:00
Martin Hauser
f4892caa51 fix(ipam): Prevent reassignment of OOB IPs
Disable reassignment of IP addresses designated as primary or OOB for
parent objects. Adds validation to block changes when an IP is marked as
the OOB IP.

Fixes #21050
2026-01-13 18:13:31 +01:00
Jeremy Stretch
a54ad24b47 Fixes #21097: Fix comparison lookups for ID filters in GraphQL API 2026-01-08 16:34:13 -05:00
7 changed files with 51 additions and 29 deletions

View File

@@ -30,13 +30,13 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v4
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }} build-mode: ${{ matrix.build-mode }}
config-file: .github/codeql/codeql-config.yml config-file: .github/codeql/codeql-config.yml
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v4
with: with:
category: "/language:${{matrix.language}}" category: "/language:${{matrix.language}}"

View File

@@ -211,12 +211,16 @@ def sync_cached_scope_fields(instance, created, **kwargs):
for model in (Prefix, Cluster, WirelessLAN): for model in (Prefix, Cluster, WirelessLAN):
qs = model.objects.filter(**filters) qs = model.objects.filter(**filters)
# Bulk update cached fields to avoid O(N) performance issues with large datasets.
# This does not trigger post_save signals, avoiding spurious change log entries.
objects_to_update = []
for obj in qs: for obj in qs:
# Recompute cache using the same logic as save() # Recompute cache using the same logic as save()
obj.cache_related_objects() obj.cache_related_objects()
obj.save(update_fields=[ objects_to_update.append(obj)
'_location',
'_site', if objects_to_update:
'_site_group', model.objects.bulk_update(
'_region', objects_to_update,
]) ['_location', '_site', '_site_group', '_region']
)

View File

@@ -31,7 +31,7 @@ class RackDimensionsPanel(panels.ObjectAttributesPanel):
outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display') outer_width = attrs.NumericAttr('outer_width', unit_accessor='get_outer_unit_display')
outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display') outer_height = attrs.NumericAttr('outer_height', unit_accessor='get_outer_unit_display')
outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display') outer_depth = attrs.NumericAttr('outer_depth', unit_accessor='get_outer_unit_display')
mounting_depth = attrs.TextAttr('mounting_depth', format_string='{}mm') mounting_depth = attrs.TextAttr('mounting_depth', format_string='{} mm')
class RackNumberingPanel(panels.ObjectAttributesPanel): class RackNumberingPanel(panels.ObjectAttributesPanel):

View File

@@ -372,8 +372,8 @@ class IPAddressForm(TenancyForm, PrimaryModelForm):
'virtual_machine_id': instance.assigned_object.virtual_machine.pk, 'virtual_machine_id': instance.assigned_object.virtual_machine.pk,
}) })
# Disable object assignment fields if the IP address is designated as primary # Disable object assignment fields if the IP address is designated as primary or OOB
if self.initial.get('primary_for_parent'): if self.initial.get('primary_for_parent') or self.initial.get('oob_for_parent'):
self.fields['interface'].disabled = True self.fields['interface'].disabled = True
self.fields['vminterface'].disabled = True self.fields['vminterface'].disabled = True
self.fields['fhrpgroup'].disabled = True self.fields['fhrpgroup'].disabled = True

View File

@@ -940,6 +940,13 @@ class IPAddress(ContactsMixin, PrimaryModel):
_("Cannot reassign IP address while it is designated as the primary IP for the parent object") _("Cannot reassign IP address while it is designated as the primary IP for the parent object")
) )
# can't use is_oob_ip as self.assigned_object might be changed
if hasattr(original_parent, 'oob_ip') and original_parent.oob_ip_id == self.pk:
if parent != original_parent:
raise ValidationError(
_("Cannot reassign IP address while it is designated as the OOB IP for the parent object")
)
# 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:
raise ValidationError({ raise ValidationError({

View File

@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
import strawberry_django import strawberry_django
from strawberry import ID from strawberry import ID
from strawberry_django import FilterLookup from strawberry_django import ComparisonFilterLookup, FilterLookup
from core.graphql.filter_mixins import ChangeLoggingMixin from core.graphql.filter_mixins import ChangeLoggingMixin
from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin from extras.graphql.filter_mixins import CustomFieldsFilterMixin, JournalEntriesFilterMixin, TagsFilterMixin
@@ -23,7 +23,7 @@ __all__ = (
@dataclass @dataclass
class BaseModelFilter: class BaseModelFilter:
id: FilterLookup[ID] | None = strawberry_django.filter_field() id: ComparisonFilterLookup[ID] | None = strawberry_django.filter_field()
class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter): class ChangeLoggedModelFilter(ChangeLoggingMixin, BaseModelFilter):

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-15 05:05+0000\n" "POT-Creation-Date: 2026-01-16 05:04+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -2435,7 +2435,7 @@ msgstr ""
msgid "Change logging is not supported for this object type ({type})." msgid "Change logging is not supported for this object type ({type})."
msgstr "" msgstr ""
#: netbox/core/models/config.py:21 netbox/core/models/data.py:282 #: netbox/core/models/config.py:21 netbox/core/models/data.py:284
#: netbox/core/models/files.py:29 netbox/core/models/jobs.py:60 #: netbox/core/models/files.py:29 netbox/core/models/jobs.py:60
#: netbox/extras/models/models.py:847 netbox/extras/models/notifications.py:39 #: netbox/extras/models/models.py:847 netbox/extras/models/notifications.py:39
#: netbox/extras/models/notifications.py:195 #: netbox/extras/models/notifications.py:195
@@ -2541,58 +2541,63 @@ msgstr ""
msgid "Unknown backend type: {type}" msgid "Unknown backend type: {type}"
msgstr "" msgstr ""
#: netbox/core/models/data.py:180 #: netbox/core/models/data.py:131
#, python-brace-format
msgid "URLs for local sources must start with {scheme} (or specify no scheme)"
msgstr ""
#: netbox/core/models/data.py:182
msgid "Cannot initiate sync; syncing already in progress." msgid "Cannot initiate sync; syncing already in progress."
msgstr "" msgstr ""
#: netbox/core/models/data.py:193 #: netbox/core/models/data.py:195
msgid "" msgid ""
"There was an error initializing the backend. A dependency needs to be " "There was an error initializing the backend. A dependency needs to be "
"installed: " "installed: "
msgstr "" msgstr ""
#: netbox/core/models/data.py:286 netbox/core/models/files.py:33 #: netbox/core/models/data.py:288 netbox/core/models/files.py:33
#: netbox/netbox/models/features.py:67 #: netbox/netbox/models/features.py:67
msgid "last updated" msgid "last updated"
msgstr "" msgstr ""
#: netbox/core/models/data.py:296 netbox/dcim/models/cables.py:622 #: netbox/core/models/data.py:298 netbox/dcim/models/cables.py:622
msgid "path" msgid "path"
msgstr "" msgstr ""
#: netbox/core/models/data.py:299 #: netbox/core/models/data.py:301
msgid "File path relative to the data source's root" msgid "File path relative to the data source's root"
msgstr "" msgstr ""
#: netbox/core/models/data.py:303 netbox/ipam/models/ip.py:507 #: netbox/core/models/data.py:305 netbox/ipam/models/ip.py:507
msgid "size" msgid "size"
msgstr "" msgstr ""
#: netbox/core/models/data.py:306 #: netbox/core/models/data.py:308
msgid "hash" msgid "hash"
msgstr "" msgstr ""
#: netbox/core/models/data.py:310 #: netbox/core/models/data.py:312
msgid "Length must be 64 hexadecimal characters." msgid "Length must be 64 hexadecimal characters."
msgstr "" msgstr ""
#: netbox/core/models/data.py:312 #: netbox/core/models/data.py:314
msgid "SHA256 hash of the file data" msgid "SHA256 hash of the file data"
msgstr "" msgstr ""
#: netbox/core/models/data.py:326 #: netbox/core/models/data.py:328
msgid "data file" msgid "data file"
msgstr "" msgstr ""
#: netbox/core/models/data.py:327 #: netbox/core/models/data.py:329
msgid "data files" msgid "data files"
msgstr "" msgstr ""
#: netbox/core/models/data.py:400 #: netbox/core/models/data.py:402
msgid "auto sync record" msgid "auto sync record"
msgstr "" msgstr ""
#: netbox/core/models/data.py:401 #: netbox/core/models/data.py:403
msgid "auto sync records" msgid "auto sync records"
msgstr "" msgstr ""
@@ -11240,7 +11245,13 @@ msgid ""
"parent object" "parent object"
msgstr "" msgstr ""
#: netbox/ipam/models/ip.py:946 #: netbox/ipam/models/ip.py:947
msgid ""
"Cannot reassign IP address while it is designated as the OOB IP for the "
"parent object"
msgstr ""
#: netbox/ipam/models/ip.py:953
msgid "Only IPv6 addresses can be assigned SLAAC status" msgid "Only IPv6 addresses can be assigned SLAAC status"
msgstr "" msgstr ""