Compare commits

...

10 Commits

Author SHA1 Message Date
Vincent Simonin
6cf86af72b Merge 605c61ef5b into 21f4036782 2025-12-11 23:52:11 -06:00
github-actions
21f4036782 Update source translation strings
Some checks are pending
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
2025-12-12 05:03:16 +00:00
bctiemann
ce3738572c Merge pull request #20967 from netbox-community/20966-remove-stick-scroll
Some checks are pending
CI / build (20.x, 3.10) (push) Waiting to run
CI / build (20.x, 3.11) (push) Waiting to run
CI / build (20.x, 3.12) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, actions) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, javascript-typescript) (push) Waiting to run
CodeQL / Analyze (${{ matrix.language }}) (none, python) (push) Waiting to run
Fixes #20966: Fix broken optgroup stickiness in ObjectType multiselect
2025-12-11 19:44:16 -05:00
bctiemann
cbb979934e Merge pull request #20958 from netbox-community/17976-manufacturer-devicetype_count
Fixes #17976: Remove devicetype_count from nested manufacturer to correct OpenAPI schema
2025-12-11 19:42:26 -05:00
bctiemann
642d83a4c6 Merge pull request #20937 from netbox-community/20560-bulk-import-prefix
Fixes #20560: Fix VLAN disambiguation in prefix bulk import
2025-12-11 19:40:59 -05:00
Jason Novinger
a06c12c6b8 Fixes #20966: Fix broken optgroup stickiness in ObjectType multiselect 2025-12-11 08:59:16 -06:00
Jeremy Stretch
59afa0b41d Fix test 2025-12-10 09:01:11 -05:00
Jeremy Stretch
14b246cb8a Fixes #17976: Remove devicetype_count from nested manufacturer to correct OpenAPI schema 2025-12-10 08:23:48 -05:00
Vincent Simonin
605c61ef5b Fix on delete cascade entity order
Since [#20708](https://github.com/netbox-community/netbox/pull/20708)
relation with a on delete RESTRICT are not deleted in the proper order.
Then the error `violate not-null constraint` occurs and breaks the
delete cascade feature.
2025-12-08 17:06:13 +01:00
Jason Novinger
9ae53fc232 Fixes #20560: Fix VLAN disambiguation in prefix bulk import 2025-12-05 16:39:28 -06:00
8 changed files with 148 additions and 71 deletions

View File

@@ -3,7 +3,7 @@ from threading import local
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db.models import CASCADE from django.db.models import CASCADE, RESTRICT
from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel from django.db.models.fields.reverse_related import ManyToManyRel, ManyToOneRel
from django.db.models.signals import m2m_changed, post_migrate, post_save, pre_delete from django.db.models.signals import m2m_changed, post_migrate, post_save, pre_delete
from django.dispatch import receiver, Signal from django.dispatch import receiver, Signal
@@ -47,6 +47,7 @@ clear_events = Signal()
# Object types # Object types
# #
@receiver(post_migrate) @receiver(post_migrate)
def update_object_types(sender, **kwargs): def update_object_types(sender, **kwargs):
""" """
@@ -133,7 +134,7 @@ def handle_changed_object(sender, instance, **kwargs):
prev_change := ObjectChange.objects.filter( prev_change := ObjectChange.objects.filter(
changed_object_type=ContentType.objects.get_for_model(instance), changed_object_type=ContentType.objects.get_for_model(instance),
changed_object_id=instance.pk, changed_object_id=instance.pk,
request_id=request.id request_id=request.id,
).first() ).first()
): ):
prev_change.postchange_data = objectchange.postchange_data prev_change.postchange_data = objectchange.postchange_data
@@ -172,9 +173,7 @@ def handle_deleted_object(sender, instance, **kwargs):
try: try:
run_validators(instance, validators) run_validators(instance, validators)
except ValidationError as e: except ValidationError as e:
raise AbortRequest( raise AbortRequest(_("Deletion is prevented by a protection rule: {message}").format(message=e))
_("Deletion is prevented by a protection rule: {message}").format(message=e)
)
# Get the current request, or bail if not set # Get the current request, or bail if not set
request = current_request.get() request = current_request.get()
@@ -221,7 +220,12 @@ def handle_deleted_object(sender, instance, **kwargs):
obj.snapshot() # Ensure the change record includes the "before" state obj.snapshot() # Ensure the change record includes the "before" state
if type(relation) is ManyToManyRel: if type(relation) is ManyToManyRel:
getattr(obj, related_field_name).remove(instance) getattr(obj, related_field_name).remove(instance)
elif type(relation) is ManyToOneRel and relation.null and relation.on_delete is not CASCADE: elif (
type(relation) is ManyToOneRel
and relation.null
and relation.on_delete is not CASCADE
and relation.on_delete is not RESTRICT
):
setattr(obj, related_field_name, None) setattr(obj, related_field_name, None)
obj.save() obj.save()
@@ -256,6 +260,7 @@ def clear_events_queue(sender, **kwargs):
# DataSource handlers # DataSource handlers
# #
@receiver(post_save, sender=DataSource) @receiver(post_save, sender=DataSource)
def enqueue_sync_job(instance, created, **kwargs): def enqueue_sync_job(instance, created, **kwargs):
""" """
@@ -267,9 +272,10 @@ def enqueue_sync_job(instance, created, **kwargs):
SyncDataSourceJob.enqueue_once(instance, interval=instance.sync_interval) SyncDataSourceJob.enqueue_once(instance, interval=instance.sync_interval)
elif not created: elif not created:
# Delete any previously scheduled recurring jobs for this DataSource # Delete any previously scheduled recurring jobs for this DataSource
for job in SyncDataSourceJob.get_jobs(instance).defer('data').filter( for job in (
interval__isnull=False, SyncDataSourceJob.get_jobs(instance)
status=JobStatusChoices.STATUS_SCHEDULED .defer('data')
.filter(interval__isnull=False, status=JobStatusChoices.STATUS_SCHEDULED)
): ):
# Call delete() per instance to ensure the associated background task is deleted as well # Call delete() per instance to ensure the associated background task is deleted as well
job.delete() job.delete()

View File

@@ -20,4 +20,4 @@ class ManufacturerSerializer(NetBoxModelSerializer):
'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'id', 'url', 'display_url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields',
'created', 'last_updated', 'devicetype_count', 'inventoryitem_count', 'platform_count', 'created', 'last_updated', 'devicetype_count', 'inventoryitem_count', 'platform_count',
] ]
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'devicetype_count') brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description')

View File

@@ -531,7 +531,7 @@ class RackReservationTest(APIViewTestCases.APIViewTestCase):
class ManufacturerTest(APIViewTestCases.APIViewTestCase): class ManufacturerTest(APIViewTestCases.APIViewTestCase):
model = Manufacturer model = Manufacturer
brief_fields = ['description', 'devicetype_count', 'display', 'id', 'name', 'slug', 'url'] brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url']
create_data = [ create_data = [
{ {
'name': 'Manufacturer 4', 'name': 'Manufacturer 4',

View File

@@ -230,10 +230,6 @@ class PrefixImportForm(ScopedImportForm, NetBoxModelImportForm):
query |= Q(**{ query |= Q(**{
f"site__{self.fields['vlan_site'].to_field_name}": vlan_site f"site__{self.fields['vlan_site'].to_field_name}": vlan_site
}) })
# Don't Forget to include VLANs without a site in the filter
query |= Q(**{
f"site__{self.fields['vlan_site'].to_field_name}__isnull": True
})
if vlan_group: if vlan_group:
query &= Q(**{ query &= Q(**{

View File

@@ -564,6 +564,82 @@ vlan: 102
self.assertEqual(prefix.vlan.vid, 102) self.assertEqual(prefix.vlan.vid, 102)
self.assertEqual(prefix.scope, site) self.assertEqual(prefix.scope, site)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_vlan_site_multiple_vlans_same_vid(self):
"""
Test import when multiple VLANs exist with the same vid but different sites.
Ref: #20560
"""
site1 = Site.objects.get(name='Site 1')
site2 = Site.objects.get(name='Site 2')
# Create VLANs with the same vid but different sites
vlan1 = VLAN.objects.create(vid=1, name='VLAN1-Site1', site=site1)
VLAN.objects.create(vid=1, name='VLAN1-Site2', site=site2) # Create ambiguity
# Import prefix with vlan_site specified
IMPORT_DATA = f"""
prefix: 10.11.0.0/22
status: active
scope_type: dcim.site
scope_id: {site1.pk}
vlan_site: {site1.name}
vlan: 1
description: LOC02-MGMT
"""
# Add all required permissions to the test user
self.add_permissions('ipam.view_prefix', 'ipam.add_prefix')
form_data = {
'data': IMPORT_DATA,
'format': 'yaml'
}
response = self.client.post(reverse('ipam:prefix_bulk_import'), data=form_data, follow=True)
self.assertHttpStatus(response, 200)
# Verify the prefix was created with the correct VLAN
prefix = Prefix.objects.get(prefix='10.11.0.0/22')
self.assertEqual(prefix.vlan, vlan1)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_vlan_site_and_global_vlan(self):
"""
Test import when a global VLAN (no site) and site-specific VLAN exist with same vid.
When vlan_site is specified, should prefer the site-specific VLAN.
Ref: #20560
"""
site1 = Site.objects.get(name='Site 1')
# Create a global VLAN (no site) and a site-specific VLAN with the same vid
VLAN.objects.create(vid=10, name='VLAN10-Global', site=None) # Create ambiguity
vlan_site = VLAN.objects.create(vid=10, name='VLAN10-Site1', site=site1)
# Import prefix with vlan_site specified
IMPORT_DATA = f"""
prefix: 10.12.0.0/22
status: active
scope_type: dcim.site
scope_id: {site1.pk}
vlan_site: {site1.name}
vlan: 10
description: Test Site-Specific VLAN
"""
# Add all required permissions to the test user
self.add_permissions('ipam.view_prefix', 'ipam.add_prefix')
form_data = {
'data': IMPORT_DATA,
'format': 'yaml'
}
response = self.client.post(reverse('ipam:prefix_bulk_import'), data=form_data, follow=True)
self.assertHttpStatus(response, 200)
# Verify the prefix was created with the site-specific VLAN (not the global one)
prefix = Prefix.objects.get(prefix='10.12.0.0/22')
self.assertEqual(prefix.vlan, vlan_site)
class IPRangeTestCase(ViewTestCases.PrimaryObjectViewTestCase): class IPRangeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = IPRange model = IPRange

File diff suppressed because one or more lines are too long

View File

@@ -36,7 +36,6 @@ form.object-edit {
// Make optgroup labels sticky when scrolling through select elements // Make optgroup labels sticky when scrolling through select elements
select[multiple] { select[multiple] {
optgroup { optgroup {
position: sticky;
top: 0; top: 0;
background-color: var(--bs-body-bg); background-color: var(--bs-body-bg);
font-style: normal; font-style: normal;

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: 2025-12-10 05:02+0000\n" "POT-Creation-Date: 2025-12-12 05:02+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"
@@ -231,7 +231,7 @@ msgstr ""
#: netbox/dcim/tables/power.py:93 netbox/dcim/tables/racks.py:125 #: netbox/dcim/tables/power.py:93 netbox/dcim/tables/racks.py:125
#: netbox/dcim/tables/racks.py:215 netbox/dcim/tables/sites.py:151 #: netbox/dcim/tables/racks.py:215 netbox/dcim/tables/sites.py:151
#: netbox/extras/filtersets.py:662 netbox/ipam/forms/bulk_edit.py:479 #: netbox/extras/filtersets.py:662 netbox/ipam/forms/bulk_edit.py:479
#: netbox/ipam/forms/bulk_import.py:489 netbox/ipam/forms/filtersets.py:161 #: netbox/ipam/forms/bulk_import.py:485 netbox/ipam/forms/filtersets.py:161
#: netbox/ipam/forms/filtersets.py:236 netbox/ipam/forms/filtersets.py:457 #: netbox/ipam/forms/filtersets.py:236 netbox/ipam/forms/filtersets.py:457
#: netbox/ipam/forms/filtersets.py:552 netbox/ipam/forms/model_forms.py:673 #: netbox/ipam/forms/filtersets.py:552 netbox/ipam/forms/model_forms.py:673
#: netbox/ipam/tables/vlans.py:90 netbox/ipam/tables/vlans.py:200 #: netbox/ipam/tables/vlans.py:90 netbox/ipam/tables/vlans.py:200
@@ -784,8 +784,8 @@ msgstr ""
#: netbox/dcim/tables/sites.py:96 netbox/dcim/tables/sites.py:155 #: netbox/dcim/tables/sites.py:96 netbox/dcim/tables/sites.py:155
#: netbox/ipam/forms/bulk_edit.py:240 netbox/ipam/forms/bulk_edit.py:290 #: netbox/ipam/forms/bulk_edit.py:240 netbox/ipam/forms/bulk_edit.py:290
#: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/bulk_edit.py:501 #: netbox/ipam/forms/bulk_edit.py:343 netbox/ipam/forms/bulk_edit.py:501
#: netbox/ipam/forms/bulk_import.py:195 netbox/ipam/forms/bulk_import.py:263 #: netbox/ipam/forms/bulk_import.py:195 netbox/ipam/forms/bulk_import.py:259
#: netbox/ipam/forms/bulk_import.py:299 netbox/ipam/forms/bulk_import.py:510 #: netbox/ipam/forms/bulk_import.py:295 netbox/ipam/forms/bulk_import.py:506
#: netbox/ipam/forms/filtersets.py:219 netbox/ipam/forms/filtersets.py:297 #: netbox/ipam/forms/filtersets.py:219 netbox/ipam/forms/filtersets.py:297
#: netbox/ipam/forms/filtersets.py:379 netbox/ipam/forms/filtersets.py:564 #: netbox/ipam/forms/filtersets.py:379 netbox/ipam/forms/filtersets.py:564
#: netbox/ipam/forms/model_forms.py:512 netbox/ipam/tables/ip.py:184 #: netbox/ipam/forms/model_forms.py:512 netbox/ipam/tables/ip.py:184
@@ -866,8 +866,8 @@ msgstr ""
#: netbox/ipam/forms/bulk_import.py:41 netbox/ipam/forms/bulk_import.py:70 #: netbox/ipam/forms/bulk_import.py:41 netbox/ipam/forms/bulk_import.py:70
#: netbox/ipam/forms/bulk_import.py:98 netbox/ipam/forms/bulk_import.py:118 #: netbox/ipam/forms/bulk_import.py:98 netbox/ipam/forms/bulk_import.py:118
#: netbox/ipam/forms/bulk_import.py:138 netbox/ipam/forms/bulk_import.py:167 #: netbox/ipam/forms/bulk_import.py:138 netbox/ipam/forms/bulk_import.py:167
#: netbox/ipam/forms/bulk_import.py:256 netbox/ipam/forms/bulk_import.py:292 #: netbox/ipam/forms/bulk_import.py:252 netbox/ipam/forms/bulk_import.py:288
#: netbox/ipam/forms/bulk_import.py:472 netbox/ipam/forms/bulk_import.py:503 #: netbox/ipam/forms/bulk_import.py:468 netbox/ipam/forms/bulk_import.py:499
#: netbox/ipam/forms/filtersets.py:50 netbox/ipam/forms/filtersets.py:70 #: netbox/ipam/forms/filtersets.py:50 netbox/ipam/forms/filtersets.py:70
#: netbox/ipam/forms/filtersets.py:102 netbox/ipam/forms/filtersets.py:123 #: netbox/ipam/forms/filtersets.py:102 netbox/ipam/forms/filtersets.py:123
#: netbox/ipam/forms/filtersets.py:146 netbox/ipam/forms/filtersets.py:182 #: netbox/ipam/forms/filtersets.py:146 netbox/ipam/forms/filtersets.py:182
@@ -1106,8 +1106,8 @@ msgstr ""
#: netbox/extras/filtersets.py:689 netbox/ipam/forms/bulk_edit.py:245 #: netbox/extras/filtersets.py:689 netbox/ipam/forms/bulk_edit.py:245
#: netbox/ipam/forms/bulk_edit.py:295 netbox/ipam/forms/bulk_edit.py:348 #: netbox/ipam/forms/bulk_edit.py:295 netbox/ipam/forms/bulk_edit.py:348
#: netbox/ipam/forms/bulk_edit.py:506 netbox/ipam/forms/bulk_import.py:200 #: netbox/ipam/forms/bulk_edit.py:506 netbox/ipam/forms/bulk_import.py:200
#: netbox/ipam/forms/bulk_import.py:268 netbox/ipam/forms/bulk_import.py:304 #: netbox/ipam/forms/bulk_import.py:264 netbox/ipam/forms/bulk_import.py:300
#: netbox/ipam/forms/bulk_import.py:515 netbox/ipam/forms/filtersets.py:247 #: netbox/ipam/forms/bulk_import.py:511 netbox/ipam/forms/filtersets.py:247
#: netbox/ipam/forms/filtersets.py:305 netbox/ipam/forms/filtersets.py:384 #: netbox/ipam/forms/filtersets.py:305 netbox/ipam/forms/filtersets.py:384
#: netbox/ipam/forms/filtersets.py:572 netbox/ipam/forms/model_forms.py:195 #: netbox/ipam/forms/filtersets.py:572 netbox/ipam/forms/model_forms.py:195
#: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:260 #: netbox/ipam/forms/model_forms.py:221 netbox/ipam/forms/model_forms.py:260
@@ -1160,8 +1160,8 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:365 netbox/dcim/forms/bulk_import.py:597 #: netbox/dcim/forms/bulk_import.py:365 netbox/dcim/forms/bulk_import.py:597
#: netbox/dcim/forms/bulk_import.py:757 netbox/dcim/forms/bulk_import.py:1250 #: netbox/dcim/forms/bulk_import.py:757 netbox/dcim/forms/bulk_import.py:1250
#: netbox/dcim/forms/bulk_import.py:1681 netbox/ipam/forms/bulk_import.py:197 #: netbox/dcim/forms/bulk_import.py:1681 netbox/ipam/forms/bulk_import.py:197
#: netbox/ipam/forms/bulk_import.py:265 netbox/ipam/forms/bulk_import.py:301 #: netbox/ipam/forms/bulk_import.py:261 netbox/ipam/forms/bulk_import.py:297
#: netbox/ipam/forms/bulk_import.py:512 netbox/ipam/forms/bulk_import.py:525 #: netbox/ipam/forms/bulk_import.py:508 netbox/ipam/forms/bulk_import.py:521
#: netbox/virtualization/forms/bulk_import.py:62 #: netbox/virtualization/forms/bulk_import.py:62
#: netbox/virtualization/forms/bulk_import.py:93 #: netbox/virtualization/forms/bulk_import.py:93
#: netbox/vpn/forms/bulk_import.py:39 netbox/vpn/forms/bulk_import.py:266 #: netbox/vpn/forms/bulk_import.py:39 netbox/vpn/forms/bulk_import.py:266
@@ -1178,9 +1178,9 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:1740 netbox/ipam/forms/bulk_import.py:45 #: netbox/dcim/forms/bulk_import.py:1740 netbox/ipam/forms/bulk_import.py:45
#: netbox/ipam/forms/bulk_import.py:74 netbox/ipam/forms/bulk_import.py:102 #: netbox/ipam/forms/bulk_import.py:74 netbox/ipam/forms/bulk_import.py:102
#: netbox/ipam/forms/bulk_import.py:122 netbox/ipam/forms/bulk_import.py:142 #: netbox/ipam/forms/bulk_import.py:122 netbox/ipam/forms/bulk_import.py:142
#: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:260 #: netbox/ipam/forms/bulk_import.py:171 netbox/ipam/forms/bulk_import.py:256
#: netbox/ipam/forms/bulk_import.py:296 netbox/ipam/forms/bulk_import.py:476 #: netbox/ipam/forms/bulk_import.py:292 netbox/ipam/forms/bulk_import.py:472
#: netbox/ipam/forms/bulk_import.py:507 #: netbox/ipam/forms/bulk_import.py:503
#: netbox/virtualization/forms/bulk_import.py:76 #: netbox/virtualization/forms/bulk_import.py:76
#: netbox/virtualization/forms/bulk_import.py:130 #: netbox/virtualization/forms/bulk_import.py:130
#: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:61 #: netbox/vpn/forms/bulk_import.py:63 netbox/wireless/forms/bulk_import.py:61
@@ -1224,7 +1224,7 @@ msgstr ""
#: netbox/dcim/forms/model_forms.py:1571 netbox/dcim/forms/model_forms.py:1738 #: netbox/dcim/forms/model_forms.py:1571 netbox/dcim/forms/model_forms.py:1738
#: netbox/dcim/forms/model_forms.py:1773 netbox/dcim/forms/model_forms.py:1903 #: netbox/dcim/forms/model_forms.py:1773 netbox/dcim/forms/model_forms.py:1903
#: netbox/dcim/tables/connections.py:65 netbox/dcim/tables/devices.py:1169 #: netbox/dcim/tables/connections.py:65 netbox/dcim/tables/devices.py:1169
#: netbox/ipam/forms/bulk_import.py:324 netbox/ipam/forms/model_forms.py:291 #: netbox/ipam/forms/bulk_import.py:320 netbox/ipam/forms/model_forms.py:291
#: netbox/ipam/forms/model_forms.py:300 netbox/ipam/tables/fhrp.py:64 #: netbox/ipam/forms/model_forms.py:300 netbox/ipam/tables/fhrp.py:64
#: netbox/ipam/tables/ip.py:330 netbox/ipam/tables/vlans.py:148 #: netbox/ipam/tables/ip.py:330 netbox/ipam/tables/vlans.py:148
#: netbox/templates/circuits/inc/circuit_termination_fields.html:52 #: netbox/templates/circuits/inc/circuit_termination_fields.html:52
@@ -1389,7 +1389,7 @@ msgstr ""
#: netbox/dcim/forms/bulk_import.py:104 netbox/dcim/forms/model_forms.py:126 #: netbox/dcim/forms/bulk_import.py:104 netbox/dcim/forms/model_forms.py:126
#: netbox/dcim/tables/sites.py:103 netbox/extras/forms/filtersets.py:582 #: netbox/dcim/tables/sites.py:103 netbox/extras/forms/filtersets.py:582
#: netbox/ipam/filtersets.py:982 netbox/ipam/forms/bulk_edit.py:488 #: netbox/ipam/filtersets.py:982 netbox/ipam/forms/bulk_edit.py:488
#: netbox/ipam/forms/bulk_import.py:496 netbox/ipam/forms/model_forms.py:571 #: netbox/ipam/forms/bulk_import.py:492 netbox/ipam/forms/model_forms.py:571
#: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:94 #: netbox/ipam/tables/fhrp.py:67 netbox/ipam/tables/vlans.py:94
#: netbox/ipam/tables/vlans.py:205 #: netbox/ipam/tables/vlans.py:205
#: netbox/templates/circuits/circuitgroupassignment.html:22 #: netbox/templates/circuits/circuitgroupassignment.html:22
@@ -1984,7 +1984,7 @@ msgstr ""
#: netbox/dcim/tables/devices.py:862 netbox/dcim/tables/devices.py:921 #: netbox/dcim/tables/devices.py:862 netbox/dcim/tables/devices.py:921
#: netbox/dcim/tables/devices.py:989 netbox/dcim/tables/devices.py:1118 #: netbox/dcim/tables/devices.py:989 netbox/dcim/tables/devices.py:1118
#: netbox/dcim/tables/modules.py:87 netbox/extras/forms/filtersets.py:389 #: netbox/dcim/tables/modules.py:87 netbox/extras/forms/filtersets.py:389
#: netbox/ipam/forms/bulk_import.py:310 netbox/ipam/forms/filtersets.py:626 #: netbox/ipam/forms/bulk_import.py:306 netbox/ipam/forms/filtersets.py:626
#: netbox/ipam/forms/model_forms.py:334 netbox/ipam/tables/vlans.py:159 #: netbox/ipam/forms/model_forms.py:334 netbox/ipam/tables/vlans.py:159
#: netbox/templates/circuits/virtualcircuittermination.html:56 #: netbox/templates/circuits/virtualcircuittermination.html:56
#: netbox/templates/dcim/consoleport.html:20 #: netbox/templates/dcim/consoleport.html:20
@@ -3185,7 +3185,7 @@ msgstr ""
#: netbox/dcim/tables/devices.py:719 netbox/dcim/tables/devices.py:929 #: netbox/dcim/tables/devices.py:719 netbox/dcim/tables/devices.py:929
#: netbox/dcim/tables/devices.py:1016 netbox/dcim/tables/devices.py:1175 #: netbox/dcim/tables/devices.py:1016 netbox/dcim/tables/devices.py:1175
#: netbox/dcim/tables/sites.py:28 netbox/dcim/tables/sites.py:62 #: netbox/dcim/tables/sites.py:28 netbox/dcim/tables/sites.py:62
#: netbox/dcim/tables/sites.py:147 netbox/ipam/forms/bulk_import.py:582 #: netbox/dcim/tables/sites.py:147 netbox/ipam/forms/bulk_import.py:578
#: netbox/ipam/forms/model_forms.py:770 netbox/ipam/tables/fhrp.py:59 #: netbox/ipam/forms/model_forms.py:770 netbox/ipam/tables/fhrp.py:59
#: netbox/ipam/tables/ip.py:336 netbox/ipam/tables/services.py:45 #: netbox/ipam/tables/ip.py:336 netbox/ipam/tables/services.py:45
#: netbox/templates/dcim/devicerole.html:34 #: netbox/templates/dcim/devicerole.html:34
@@ -3963,7 +3963,7 @@ msgid "Is assigned"
msgstr "" msgstr ""
#: netbox/dcim/filtersets.py:1826 netbox/dcim/forms/bulk_import.py:1355 #: netbox/dcim/filtersets.py:1826 netbox/dcim/forms/bulk_import.py:1355
#: netbox/ipam/forms/bulk_import.py:338 #: netbox/ipam/forms/bulk_import.py:334
msgid "Is primary" msgid "Is primary"
msgstr "" msgstr ""
@@ -3991,7 +3991,7 @@ msgstr ""
#: netbox/ipam/filtersets.py:579 netbox/ipam/filtersets.py:590 #: netbox/ipam/filtersets.py:579 netbox/ipam/filtersets.py:590
#: netbox/ipam/forms/bulk_edit.py:226 netbox/ipam/forms/bulk_edit.py:282 #: netbox/ipam/forms/bulk_edit.py:226 netbox/ipam/forms/bulk_edit.py:282
#: netbox/ipam/forms/bulk_edit.py:329 netbox/ipam/forms/bulk_import.py:160 #: netbox/ipam/forms/bulk_edit.py:329 netbox/ipam/forms/bulk_import.py:160
#: netbox/ipam/forms/bulk_import.py:249 netbox/ipam/forms/bulk_import.py:285 #: netbox/ipam/forms/bulk_import.py:245 netbox/ipam/forms/bulk_import.py:281
#: netbox/ipam/forms/filtersets.py:69 netbox/ipam/forms/filtersets.py:180 #: netbox/ipam/forms/filtersets.py:69 netbox/ipam/forms/filtersets.py:180
#: netbox/ipam/forms/filtersets.py:332 netbox/ipam/forms/model_forms.py:66 #: netbox/ipam/forms/filtersets.py:332 netbox/ipam/forms/model_forms.py:66
#: netbox/ipam/forms/model_forms.py:209 netbox/ipam/forms/model_forms.py:257 #: netbox/ipam/forms/model_forms.py:209 netbox/ipam/forms/model_forms.py:257
@@ -4856,7 +4856,7 @@ msgid "available options"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:138 netbox/dcim/forms/bulk_import.py:633 #: netbox/dcim/forms/bulk_import.py:138 netbox/dcim/forms/bulk_import.py:633
#: netbox/dcim/forms/bulk_import.py:1650 netbox/ipam/forms/bulk_import.py:493 #: netbox/dcim/forms/bulk_import.py:1650 netbox/ipam/forms/bulk_import.py:489
#: netbox/virtualization/forms/bulk_import.py:69 #: netbox/virtualization/forms/bulk_import.py:69
#: netbox/virtualization/forms/bulk_import.py:100 #: netbox/virtualization/forms/bulk_import.py:100
msgid "Assigned site" msgid "Assigned site"
@@ -5168,7 +5168,7 @@ msgid "Assigned Q-in-Q Service VLAN ID (filtered by VLAN group)"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1028 netbox/ipam/forms/bulk_import.py:164 #: netbox/dcim/forms/bulk_import.py:1028 netbox/ipam/forms/bulk_import.py:164
#: netbox/ipam/forms/bulk_import.py:253 netbox/ipam/forms/bulk_import.py:289 #: netbox/ipam/forms/bulk_import.py:249 netbox/ipam/forms/bulk_import.py:285
#: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:293 #: netbox/ipam/forms/filtersets.py:210 netbox/ipam/forms/filtersets.py:293
#: netbox/ipam/forms/filtersets.py:360 #: netbox/ipam/forms/filtersets.py:360
#: netbox/virtualization/forms/bulk_import.py:220 #: netbox/virtualization/forms/bulk_import.py:220
@@ -5247,11 +5247,11 @@ msgstr ""
msgid "Component type must be specified when component name is specified" msgid "Component type must be specified when component name is specified"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1338 netbox/ipam/forms/bulk_import.py:314 #: netbox/dcim/forms/bulk_import.py:1338 netbox/ipam/forms/bulk_import.py:310
msgid "Parent device of assigned interface (if any)" msgid "Parent device of assigned interface (if any)"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1341 netbox/ipam/forms/bulk_import.py:317 #: netbox/dcim/forms/bulk_import.py:1341 netbox/ipam/forms/bulk_import.py:313
#: netbox/virtualization/filtersets.py:259 #: netbox/virtualization/filtersets.py:259
#: netbox/virtualization/filtersets.py:310 #: netbox/virtualization/filtersets.py:310
#: netbox/virtualization/forms/bulk_edit.py:182 #: netbox/virtualization/forms/bulk_edit.py:182
@@ -5265,12 +5265,12 @@ msgstr ""
msgid "Virtual machine" msgid "Virtual machine"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1345 netbox/ipam/forms/bulk_import.py:321 #: netbox/dcim/forms/bulk_import.py:1345 netbox/ipam/forms/bulk_import.py:317
msgid "Parent VM of assigned interface (if any)" msgid "Parent VM of assigned interface (if any)"
msgstr "" msgstr ""
#: netbox/dcim/forms/bulk_import.py:1352 netbox/ipam/filtersets.py:1035 #: netbox/dcim/forms/bulk_import.py:1352 netbox/ipam/filtersets.py:1035
#: netbox/ipam/forms/bulk_import.py:328 #: netbox/ipam/forms/bulk_import.py:324
msgid "Assigned interface" msgid "Assigned interface"
msgstr "" msgstr ""
@@ -5654,7 +5654,7 @@ msgstr ""
msgid "Please select a {scope_type}." msgid "Please select a {scope_type}."
msgstr "" msgstr ""
#: netbox/dcim/forms/mixins.py:117 netbox/ipam/forms/bulk_import.py:466 #: netbox/dcim/forms/mixins.py:117 netbox/ipam/forms/bulk_import.py:462
msgid "Scope type (app & model)" msgid "Scope type (app & model)"
msgstr "" msgstr ""
@@ -6404,7 +6404,7 @@ msgstr ""
#: netbox/dcim/models/device_components.py:605 #: netbox/dcim/models/device_components.py:605
#: netbox/dcim/tables/devices.py:631 netbox/ipam/forms/bulk_edit.py:521 #: netbox/dcim/tables/devices.py:631 netbox/ipam/forms/bulk_edit.py:521
#: netbox/ipam/forms/bulk_import.py:528 netbox/ipam/forms/filtersets.py:587 #: netbox/ipam/forms/bulk_import.py:524 netbox/ipam/forms/filtersets.py:587
#: netbox/ipam/forms/model_forms.py:694 netbox/ipam/tables/vlans.py:109 #: netbox/ipam/forms/model_forms.py:694 netbox/ipam/tables/vlans.py:109
#: netbox/templates/dcim/interface.html:86 netbox/templates/ipam/vlan.html:77 #: netbox/templates/dcim/interface.html:86 netbox/templates/ipam/vlan.html:77
#: netbox/templates/virtualization/vminterface.html:60 #: netbox/templates/virtualization/vminterface.html:60
@@ -7324,8 +7324,8 @@ msgid "Locally-assigned identifier"
msgstr "" msgstr ""
#: netbox/dcim/models/racks.py:305 netbox/ipam/forms/bulk_import.py:204 #: netbox/dcim/models/racks.py:305 netbox/ipam/forms/bulk_import.py:204
#: netbox/ipam/forms/bulk_import.py:272 netbox/ipam/forms/bulk_import.py:307 #: netbox/ipam/forms/bulk_import.py:268 netbox/ipam/forms/bulk_import.py:303
#: netbox/ipam/forms/bulk_import.py:519 #: netbox/ipam/forms/bulk_import.py:515
#: netbox/virtualization/forms/bulk_import.py:123 #: netbox/virtualization/forms/bulk_import.py:123
msgid "Functional role" msgid "Functional role"
msgstr "" msgstr ""
@@ -7576,7 +7576,7 @@ msgid "U Height"
msgstr "" msgstr ""
#: netbox/dcim/tables/devices.py:210 netbox/dcim/tables/devices.py:1128 #: netbox/dcim/tables/devices.py:210 netbox/dcim/tables/devices.py:1128
#: netbox/ipam/forms/bulk_import.py:601 netbox/ipam/forms/model_forms.py:317 #: netbox/ipam/forms/bulk_import.py:597 netbox/ipam/forms/model_forms.py:317
#: netbox/ipam/forms/model_forms.py:330 netbox/ipam/tables/ip.py:314 #: netbox/ipam/forms/model_forms.py:330 netbox/ipam/tables/ip.py:314
#: netbox/ipam/tables/ip.py:381 netbox/ipam/tables/ip.py:391 #: netbox/ipam/tables/ip.py:381 netbox/ipam/tables/ip.py:391
#: netbox/ipam/tables/ip.py:414 netbox/templates/ipam/ipaddress.html:11 #: netbox/ipam/tables/ip.py:414 netbox/templates/ipam/ipaddress.html:11
@@ -10419,8 +10419,8 @@ msgid "DNS name"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_edit.py:376 netbox/ipam/forms/bulk_edit.py:573 #: netbox/ipam/forms/bulk_edit.py:376 netbox/ipam/forms/bulk_edit.py:573
#: netbox/ipam/forms/bulk_import.py:447 netbox/ipam/forms/bulk_import.py:565 #: netbox/ipam/forms/bulk_import.py:443 netbox/ipam/forms/bulk_import.py:561
#: netbox/ipam/forms/bulk_import.py:593 netbox/ipam/forms/filtersets.py:414 #: netbox/ipam/forms/bulk_import.py:589 netbox/ipam/forms/filtersets.py:414
#: netbox/ipam/forms/filtersets.py:604 netbox/templates/ipam/fhrpgroup.html:22 #: netbox/ipam/forms/filtersets.py:604 netbox/templates/ipam/fhrpgroup.html:22
#: netbox/templates/ipam/inc/panels/fhrp_groups.html:24 #: netbox/templates/ipam/inc/panels/fhrp_groups.html:24
#: netbox/templates/ipam/service.html:34 #: netbox/templates/ipam/service.html:34
@@ -10464,7 +10464,7 @@ msgstr ""
msgid "VLAN ID ranges" msgid "VLAN ID ranges"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_import.py:522 #: netbox/ipam/forms/bulk_edit.py:516 netbox/ipam/forms/bulk_import.py:518
#: netbox/ipam/forms/filtersets.py:579 netbox/ipam/models/vlans.py:250 #: netbox/ipam/forms/filtersets.py:579 netbox/ipam/models/vlans.py:250
#: netbox/ipam/tables/vlans.py:106 #: netbox/ipam/tables/vlans.py:106
msgid "Q-in-Q role" msgid "Q-in-Q role"
@@ -10478,7 +10478,7 @@ msgstr ""
msgid "Site & Group" msgid "Site & Group"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_edit.py:557 netbox/ipam/forms/bulk_import.py:552 #: netbox/ipam/forms/bulk_edit.py:557 netbox/ipam/forms/bulk_import.py:548
#: netbox/ipam/forms/model_forms.py:726 netbox/ipam/tables/vlans.py:259 #: netbox/ipam/forms/model_forms.py:726 netbox/ipam/tables/vlans.py:259
#: netbox/templates/ipam/vlantranslationrule.html:14 #: netbox/templates/ipam/vlantranslationrule.html:14
#: netbox/vpn/forms/model_forms.py:322 netbox/vpn/forms/model_forms.py:359 #: netbox/vpn/forms/model_forms.py:322 netbox/vpn/forms/model_forms.py:359
@@ -10523,86 +10523,86 @@ msgstr ""
msgid "Scope ID" msgid "Scope ID"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:331 netbox/ipam/forms/filtersets.py:636 #: netbox/ipam/forms/bulk_import.py:327 netbox/ipam/forms/filtersets.py:636
#: netbox/ipam/forms/model_forms.py:306 netbox/ipam/forms/model_forms.py:336 #: netbox/ipam/forms/model_forms.py:306 netbox/ipam/forms/model_forms.py:336
#: netbox/ipam/forms/model_forms.py:517 netbox/templates/ipam/fhrpgroup.html:19 #: netbox/ipam/forms/model_forms.py:517 netbox/templates/ipam/fhrpgroup.html:19
msgid "FHRP Group" msgid "FHRP Group"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:335 #: netbox/ipam/forms/bulk_import.py:331
msgid "Assigned FHRP Group name" msgid "Assigned FHRP Group name"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:339 #: netbox/ipam/forms/bulk_import.py:335
msgid "Make this the primary IP for the assigned device" msgid "Make this the primary IP for the assigned device"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:343 #: netbox/ipam/forms/bulk_import.py:339
msgid "Is out-of-band" msgid "Is out-of-band"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:344 #: netbox/ipam/forms/bulk_import.py:340
msgid "Designate this as the out-of-band IP address for the assigned device" msgid "Designate this as the out-of-band IP address for the assigned device"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:398 #: netbox/ipam/forms/bulk_import.py:394
msgid "No device or virtual machine specified; cannot set as primary IP" msgid "No device or virtual machine specified; cannot set as primary IP"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:402 #: netbox/ipam/forms/bulk_import.py:398
msgid "No device specified; cannot set as out-of-band IP" msgid "No device specified; cannot set as out-of-band IP"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:406 #: netbox/ipam/forms/bulk_import.py:402
msgid "Cannot set out-of-band IP for virtual machines" msgid "Cannot set out-of-band IP for virtual machines"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:410 #: netbox/ipam/forms/bulk_import.py:406
msgid "No interface specified; cannot set as primary IP" msgid "No interface specified; cannot set as primary IP"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:414 #: netbox/ipam/forms/bulk_import.py:410
msgid "No interface specified; cannot set as out-of-band IP" msgid "No interface specified; cannot set as out-of-band IP"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:451 #: netbox/ipam/forms/bulk_import.py:447
msgid "Auth type" msgid "Auth type"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:500 #: netbox/ipam/forms/bulk_import.py:496
msgid "Assigned VLAN group" msgid "Assigned VLAN group"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:532 #: netbox/ipam/forms/bulk_import.py:528
msgid "Service VLAN (for Q-in-Q/802.1ad customer VLANs)" msgid "Service VLAN (for Q-in-Q/802.1ad customer VLANs)"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:555 netbox/ipam/models/vlans.py:369 #: netbox/ipam/forms/bulk_import.py:551 netbox/ipam/models/vlans.py:369
msgid "VLAN translation policy" msgid "VLAN translation policy"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:567 netbox/ipam/forms/bulk_import.py:595 #: netbox/ipam/forms/bulk_import.py:563 netbox/ipam/forms/bulk_import.py:591
msgid "IP protocol" msgid "IP protocol"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:579 #: netbox/ipam/forms/bulk_import.py:575
msgid "Parent type (app & model)" msgid "Parent type (app & model)"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:586 #: netbox/ipam/forms/bulk_import.py:582
msgid "Parent object name" msgid "Parent object name"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:590 #: netbox/ipam/forms/bulk_import.py:586
msgid "Parent object ID" msgid "Parent object ID"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:642 #: netbox/ipam/forms/bulk_import.py:638
msgid "" msgid ""
"One of parent or parent_object_id must be included with parent_object_type" "One of parent or parent_object_id must be included with parent_object_type"
msgstr "" msgstr ""
#: netbox/ipam/forms/bulk_import.py:655 #: netbox/ipam/forms/bulk_import.py:651
#, python-brace-format #, python-brace-format
msgid "{ip} is not assigned to this parent." msgid "{ip} is not assigned to this parent."
msgstr "" msgstr ""