Merge branch 'netbox-community:main' into closes-20817-Fix-datasource-sync-broken-when-cron-is-set

This commit is contained in:
Idris Foughali 2025-12-05 14:51:56 +01:00 committed by GitHub
commit 09d1049267
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 133 additions and 99 deletions

View File

@ -1,3 +1,5 @@
import decimal
import django.core.validators import django.core.validators
from django.db import migrations, models from django.db import migrations, models
@ -17,8 +19,8 @@ class Migration(migrations.Migration):
max_digits=8, max_digits=8,
null=True, null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(-90.0), django.core.validators.MinValueValidator(decimal.Decimal('-90.0')),
django.core.validators.MaxValueValidator(90.0), django.core.validators.MaxValueValidator(decimal.Decimal('90.0'))
], ],
), ),
), ),
@ -31,8 +33,8 @@ class Migration(migrations.Migration):
max_digits=9, max_digits=9,
null=True, null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(-180.0), django.core.validators.MinValueValidator(decimal.Decimal('-180.0')),
django.core.validators.MaxValueValidator(180.0), django.core.validators.MaxValueValidator(decimal.Decimal('180.0'))
], ],
), ),
), ),
@ -45,8 +47,8 @@ class Migration(migrations.Migration):
max_digits=8, max_digits=8,
null=True, null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(-90.0), django.core.validators.MinValueValidator(decimal.Decimal('-90.0')),
django.core.validators.MaxValueValidator(90.0), django.core.validators.MaxValueValidator(decimal.Decimal('90.0'))
], ],
), ),
), ),
@ -59,8 +61,8 @@ class Migration(migrations.Migration):
max_digits=9, max_digits=9,
null=True, null=True,
validators=[ validators=[
django.core.validators.MinValueValidator(-180.0), django.core.validators.MinValueValidator(decimal.Decimal('-180.0')),
django.core.validators.MaxValueValidator(180.0), django.core.validators.MaxValueValidator(decimal.Decimal('180.0'))
], ],
), ),
), ),

View File

@ -646,7 +646,10 @@ class Device(
decimal_places=6, decimal_places=6,
blank=True, blank=True,
null=True, null=True,
validators=[MinValueValidator(-90.0), MaxValueValidator(90.0)], validators=[
MinValueValidator(decimal.Decimal('-90.0')),
MaxValueValidator(decimal.Decimal('90.0'))
],
help_text=_("GPS coordinate in decimal format (xx.yyyyyy)") help_text=_("GPS coordinate in decimal format (xx.yyyyyy)")
) )
longitude = models.DecimalField( longitude = models.DecimalField(
@ -655,7 +658,10 @@ class Device(
decimal_places=6, decimal_places=6,
blank=True, blank=True,
null=True, null=True,
validators=[MinValueValidator(-180.0), MaxValueValidator(180.0)], validators=[
MinValueValidator(decimal.Decimal('-180.0')),
MaxValueValidator(decimal.Decimal('180.0'))
],
help_text=_("GPS coordinate in decimal format (xx.yyyyyy)") help_text=_("GPS coordinate in decimal format (xx.yyyyyy)")
) )
services = GenericRelation( services = GenericRelation(

View File

@ -1,3 +1,5 @@
import decimal
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
@ -211,7 +213,10 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
decimal_places=6, decimal_places=6,
blank=True, blank=True,
null=True, null=True,
validators=[MinValueValidator(-90.0), MaxValueValidator(90.0)], validators=[
MinValueValidator(decimal.Decimal('-90.0')),
MaxValueValidator(decimal.Decimal('90.0'))
],
help_text=_('GPS coordinate in decimal format (xx.yyyyyy)') help_text=_('GPS coordinate in decimal format (xx.yyyyyy)')
) )
longitude = models.DecimalField( longitude = models.DecimalField(
@ -220,7 +225,10 @@ class Site(ContactsMixin, ImageAttachmentsMixin, PrimaryModel):
decimal_places=6, decimal_places=6,
blank=True, blank=True,
null=True, null=True,
validators=[MinValueValidator(-180.0), MaxValueValidator(180.0)], validators=[
MinValueValidator(decimal.Decimal('-180.0')),
MaxValueValidator(decimal.Decimal('180.0'))
],
help_text=_('GPS coordinate in decimal format (xx.yyyyyy)') help_text=_('GPS coordinate in decimal format (xx.yyyyyy)')
) )

View File

@ -2,11 +2,14 @@ import logging
import traceback import traceback
from contextlib import ExitStack from contextlib import ExitStack
from django.db import transaction from django.db import router, transaction
from django.db import DEFAULT_DB_ALIAS
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from core.signals import clear_events from core.signals import clear_events
from dcim.models import Device
from extras.models import Script as ScriptModel from extras.models import Script as ScriptModel
from netbox.context_managers import event_tracking
from netbox.jobs import JobRunner from netbox.jobs import JobRunner
from netbox.registry import registry from netbox.registry import registry
from utilities.exceptions import AbortScript, AbortTransaction from utilities.exceptions import AbortScript, AbortTransaction
@ -42,10 +45,21 @@ class ScriptJob(JobRunner):
# A script can modify multiple models so need to do an atomic lock on # A script can modify multiple models so need to do an atomic lock on
# both the default database (for non ChangeLogged models) and potentially # both the default database (for non ChangeLogged models) and potentially
# any other database (for ChangeLogged models) # any other database (for ChangeLogged models)
with transaction.atomic(): changeloged_db = router.db_for_write(Device)
script.output = script.run(data, commit) with transaction.atomic(using=DEFAULT_DB_ALIAS):
if not commit: # If branch database is different from default, wrap in a second atomic transaction
raise AbortTransaction() # Note: Don't add any extra code between the two atomic transactions,
# otherwise the changes might get committed to the default database
# if there are any raised exceptions.
if changeloged_db != DEFAULT_DB_ALIAS:
with transaction.atomic(using=changeloged_db):
script.output = script.run(data, commit)
if not commit:
raise AbortTransaction()
else:
script.output = script.run(data, commit)
if not commit:
raise AbortTransaction()
except AbortTransaction: except AbortTransaction:
script.log_info(message=_("Database changes have been reverted automatically.")) script.log_info(message=_("Database changes have been reverted automatically."))
if script.failed: if script.failed:
@ -108,14 +122,14 @@ class ScriptJob(JobRunner):
script.request = request script.request = request
self.logger.debug(f"Request ID: {request.id if request else None}") self.logger.debug(f"Request ID: {request.id if request else None}")
# Execute the script. If commit is True, wrap it with the event_tracking context manager to ensure we process
# change logging, event rules, etc.
if commit: if commit:
self.logger.info("Executing script (commit enabled)") self.logger.info("Executing script (commit enabled)")
with ExitStack() as stack:
for request_processor in registry['request_processors']:
stack.enter_context(request_processor(request))
self.run_script(script, request, data, commit)
else: else:
self.logger.warning("Executing script (commit disabled)") self.logger.warning("Executing script (commit disabled)")
with ExitStack() as stack:
for request_processor in registry['request_processors']:
if not commit and request_processor is event_tracking:
continue
stack.enter_context(request_processor(request))
self.run_script(script, request, data, commit) self.run_script(script, request, data, commit)

View File

@ -559,6 +559,7 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
form.instance._replicated_base = hasattr(self.form, "replication_fields") form.instance._replicated_base = hasattr(self.form, "replication_fields")
if form.is_valid(): if form.is_valid():
changelog_message = form.cleaned_data.pop('changelog_message', '')
new_components = [] new_components = []
data = deepcopy(request.POST) data = deepcopy(request.POST)
pattern_count = len(form.cleaned_data[self.form.replication_fields[0]]) pattern_count = len(form.cleaned_data[self.form.replication_fields[0]])
@ -585,6 +586,9 @@ class ComponentCreateView(GetReturnURLMixin, BaseObjectView):
# Create the new components # Create the new components
new_objs = [] new_objs = []
for component_form in new_components: for component_form in new_components:
# Record changelog message (if any)
if changelog_message:
component_form.instance._changelog_message = changelog_message
obj = component_form.save() obj = component_form.save()
new_objs.append(obj) new_objs.append(obj)

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-11-26 05:01+0000\n" "POT-Creation-Date: 2025-12-04 05:01+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"
@ -1469,10 +1469,10 @@ msgstr ""
#: netbox/core/models/jobs.py:95 netbox/dcim/models/cables.py:51 #: netbox/core/models/jobs.py:95 netbox/dcim/models/cables.py:51
#: netbox/dcim/models/device_components.py:488 #: netbox/dcim/models/device_components.py:488
#: netbox/dcim/models/device_components.py:1319 #: netbox/dcim/models/device_components.py:1319
#: netbox/dcim/models/devices.py:580 netbox/dcim/models/devices.py:1196 #: netbox/dcim/models/devices.py:580 netbox/dcim/models/devices.py:1202
#: netbox/dcim/models/modules.py:210 netbox/dcim/models/power.py:94 #: netbox/dcim/models/modules.py:210 netbox/dcim/models/power.py:94
#: netbox/dcim/models/racks.py:294 netbox/dcim/models/racks.py:677 #: netbox/dcim/models/racks.py:294 netbox/dcim/models/racks.py:677
#: netbox/dcim/models/sites.py:155 netbox/dcim/models/sites.py:273 #: netbox/dcim/models/sites.py:157 netbox/dcim/models/sites.py:281
#: netbox/ipam/models/ip.py:243 netbox/ipam/models/ip.py:529 #: netbox/ipam/models/ip.py:243 netbox/ipam/models/ip.py:529
#: netbox/ipam/models/ip.py:758 netbox/ipam/models/vlans.py:228 #: netbox/ipam/models/ip.py:758 netbox/ipam/models/vlans.py:228
#: netbox/virtualization/models/clusters.py:70 #: netbox/virtualization/models/clusters.py:70
@ -1603,10 +1603,10 @@ msgstr ""
#: netbox/core/models/jobs.py:56 #: netbox/core/models/jobs.py:56
#: netbox/dcim/models/device_component_templates.py:44 #: netbox/dcim/models/device_component_templates.py:44
#: netbox/dcim/models/device_components.py:53 netbox/dcim/models/devices.py:524 #: netbox/dcim/models/device_components.py:53 netbox/dcim/models/devices.py:524
#: netbox/dcim/models/devices.py:1122 netbox/dcim/models/devices.py:1191 #: netbox/dcim/models/devices.py:1128 netbox/dcim/models/devices.py:1197
#: netbox/dcim/models/modules.py:32 netbox/dcim/models/power.py:38 #: netbox/dcim/models/modules.py:32 netbox/dcim/models/power.py:38
#: netbox/dcim/models/power.py:89 netbox/dcim/models/racks.py:263 #: netbox/dcim/models/power.py:89 netbox/dcim/models/racks.py:263
#: netbox/dcim/models/sites.py:143 netbox/extras/models/configs.py:36 #: netbox/dcim/models/sites.py:145 netbox/extras/models/configs.py:36
#: netbox/extras/models/configs.py:78 netbox/extras/models/configs.py:272 #: netbox/extras/models/configs.py:78 netbox/extras/models/configs.py:272
#: netbox/extras/models/customfields.py:94 netbox/extras/models/models.py:60 #: netbox/extras/models/customfields.py:94 netbox/extras/models/models.py:60
#: netbox/extras/models/models.py:165 netbox/extras/models/models.py:308 #: netbox/extras/models/models.py:165 netbox/extras/models/models.py:308
@ -1637,7 +1637,7 @@ msgid "Full name of the provider"
msgstr "" msgstr ""
#: netbox/circuits/models/providers.py:28 netbox/dcim/models/devices.py:89 #: netbox/circuits/models/providers.py:28 netbox/dcim/models/devices.py:89
#: netbox/dcim/models/racks.py:143 netbox/dcim/models/sites.py:150 #: netbox/dcim/models/racks.py:143 netbox/dcim/models/sites.py:152
#: netbox/extras/models/models.py:474 netbox/ipam/models/asns.py:24 #: netbox/extras/models/models.py:474 netbox/ipam/models/asns.py:24
#: netbox/ipam/models/vlans.py:43 netbox/netbox/models/__init__.py:146 #: netbox/ipam/models/vlans.py:43 netbox/netbox/models/__init__.py:146
#: netbox/netbox/models/__init__.py:195 netbox/tenancy/models/tenants.py:25 #: netbox/netbox/models/__init__.py:195 netbox/tenancy/models/tenants.py:25
@ -3816,8 +3816,8 @@ msgstr ""
#: netbox/dcim/filtersets.py:1197 netbox/dcim/forms/filtersets.py:848 #: netbox/dcim/filtersets.py:1197 netbox/dcim/forms/filtersets.py:848
#: netbox/dcim/forms/filtersets.py:1473 netbox/dcim/forms/filtersets.py:1688 #: netbox/dcim/forms/filtersets.py:1473 netbox/dcim/forms/filtersets.py:1688
#: netbox/dcim/forms/model_forms.py:1900 netbox/dcim/models/devices.py:1292 #: netbox/dcim/forms/model_forms.py:1900 netbox/dcim/models/devices.py:1298
#: netbox/dcim/models/devices.py:1312 netbox/virtualization/filtersets.py:201 #: netbox/dcim/models/devices.py:1318 netbox/virtualization/filtersets.py:201
#: netbox/virtualization/filtersets.py:273 #: netbox/virtualization/filtersets.py:273
#: netbox/virtualization/forms/filtersets.py:178 #: netbox/virtualization/forms/filtersets.py:178
#: netbox/virtualization/forms/filtersets.py:231 #: netbox/virtualization/forms/filtersets.py:231
@ -6857,12 +6857,12 @@ msgstr ""
msgid "rack face" msgid "rack face"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:598 netbox/dcim/models/devices.py:1212 #: netbox/dcim/models/devices.py:598 netbox/dcim/models/devices.py:1218
#: netbox/virtualization/models/virtualmachines.py:94 #: netbox/virtualization/models/virtualmachines.py:94
msgid "primary IPv4" msgid "primary IPv4"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:606 netbox/dcim/models/devices.py:1220 #: netbox/dcim/models/devices.py:606 netbox/dcim/models/devices.py:1226
#: netbox/virtualization/models/virtualmachines.py:102 #: netbox/virtualization/models/virtualmachines.py:102
msgid "primary IPv6" msgid "primary IPv6"
msgstr "" msgstr ""
@ -6887,191 +6887,191 @@ msgstr ""
msgid "Virtual chassis master election priority" msgid "Virtual chassis master election priority"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:644 netbox/dcim/models/sites.py:209 #: netbox/dcim/models/devices.py:644 netbox/dcim/models/sites.py:211
msgid "latitude" msgid "latitude"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:650 netbox/dcim/models/devices.py:659 #: netbox/dcim/models/devices.py:653 netbox/dcim/models/devices.py:665
#: netbox/dcim/models/sites.py:215 netbox/dcim/models/sites.py:224 #: netbox/dcim/models/sites.py:220 netbox/dcim/models/sites.py:232
msgid "GPS coordinate in decimal format (xx.yyyyyy)" msgid "GPS coordinate in decimal format (xx.yyyyyy)"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:653 netbox/dcim/models/sites.py:218 #: netbox/dcim/models/devices.py:656 netbox/dcim/models/sites.py:223
msgid "longitude" msgid "longitude"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:733 #: netbox/dcim/models/devices.py:739
msgid "Device name must be unique per site." msgid "Device name must be unique per site."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:744 #: netbox/dcim/models/devices.py:750
msgid "device" msgid "device"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:745 #: netbox/dcim/models/devices.py:751
msgid "devices" msgid "devices"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:764 #: netbox/dcim/models/devices.py:770
#, python-brace-format #, python-brace-format
msgid "Rack {rack} does not belong to site {site}." msgid "Rack {rack} does not belong to site {site}."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:769 #: netbox/dcim/models/devices.py:775
#, python-brace-format #, python-brace-format
msgid "Location {location} does not belong to site {site}." msgid "Location {location} does not belong to site {site}."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:775 #: netbox/dcim/models/devices.py:781
#, python-brace-format #, python-brace-format
msgid "Rack {rack} does not belong to location {location}." msgid "Rack {rack} does not belong to location {location}."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:782 #: netbox/dcim/models/devices.py:788
msgid "Cannot select a rack face without assigning a rack." msgid "Cannot select a rack face without assigning a rack."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:786 #: netbox/dcim/models/devices.py:792
msgid "Cannot select a rack position without assigning a rack." msgid "Cannot select a rack position without assigning a rack."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:792 #: netbox/dcim/models/devices.py:798
msgid "Position must be in increments of 0.5 rack units." msgid "Position must be in increments of 0.5 rack units."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:796 #: netbox/dcim/models/devices.py:802
msgid "Must specify rack face when defining rack position." msgid "Must specify rack face when defining rack position."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:804 #: netbox/dcim/models/devices.py:810
#, python-brace-format #, python-brace-format
msgid "A 0U device type ({device_type}) cannot be assigned to a rack position." msgid "A 0U device type ({device_type}) cannot be assigned to a rack position."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:815 #: netbox/dcim/models/devices.py:821
msgid "" msgid ""
"Child device types cannot be assigned to a rack face. This is an attribute " "Child device types cannot be assigned to a rack face. This is an attribute "
"of the parent device." "of the parent device."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:822 #: netbox/dcim/models/devices.py:828
msgid "" msgid ""
"Child device types cannot be assigned to a rack position. This is an " "Child device types cannot be assigned to a rack position. This is an "
"attribute of the parent device." "attribute of the parent device."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:836 #: netbox/dcim/models/devices.py:842
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"U{position} is already occupied or does not have sufficient space to " "U{position} is already occupied or does not have sufficient space to "
"accommodate this device type: {device_type} ({u_height}U)" "accommodate this device type: {device_type} ({u_height}U)"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:851 #: netbox/dcim/models/devices.py:857
#, python-brace-format #, python-brace-format
msgid "{ip} is not an IPv4 address." msgid "{ip} is not an IPv4 address."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:863 netbox/dcim/models/devices.py:881 #: netbox/dcim/models/devices.py:869 netbox/dcim/models/devices.py:887
#, python-brace-format #, python-brace-format
msgid "The specified IP address ({ip}) is not assigned to this device." msgid "The specified IP address ({ip}) is not assigned to this device."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:869 #: netbox/dcim/models/devices.py:875
#, python-brace-format #, python-brace-format
msgid "{ip} is not an IPv6 address." msgid "{ip} is not an IPv6 address."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:899 #: netbox/dcim/models/devices.py:905
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"The assigned platform is limited to {platform_manufacturer} device types, " "The assigned platform is limited to {platform_manufacturer} device types, "
"but this device's type belongs to {devicetype_manufacturer}." "but this device's type belongs to {devicetype_manufacturer}."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:910 #: netbox/dcim/models/devices.py:916
#, python-brace-format #, python-brace-format
msgid "The assigned cluster belongs to a different site ({site})" msgid "The assigned cluster belongs to a different site ({site})"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:917 #: netbox/dcim/models/devices.py:923
#, python-brace-format #, python-brace-format
msgid "The assigned cluster belongs to a different location ({location})" msgid "The assigned cluster belongs to a different location ({location})"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:925 #: netbox/dcim/models/devices.py:931
msgid "A device assigned to a virtual chassis must have its position defined." msgid "A device assigned to a virtual chassis must have its position defined."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:931 #: netbox/dcim/models/devices.py:937
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Device cannot be removed from virtual chassis {virtual_chassis} because it " "Device cannot be removed from virtual chassis {virtual_chassis} because it "
"is currently designated as its master." "is currently designated as its master."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1127 #: netbox/dcim/models/devices.py:1133
msgid "domain" msgid "domain"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1140 netbox/dcim/models/devices.py:1141 #: netbox/dcim/models/devices.py:1146 netbox/dcim/models/devices.py:1147
msgid "virtual chassis" msgid "virtual chassis"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1153 #: netbox/dcim/models/devices.py:1159
#, python-brace-format #, python-brace-format
msgid "The selected master ({master}) is not assigned to this virtual chassis." msgid "The selected master ({master}) is not assigned to this virtual chassis."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1168 #: netbox/dcim/models/devices.py:1174
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"Unable to delete virtual chassis {self}. There are member interfaces which " "Unable to delete virtual chassis {self}. There are member interfaces which "
"form a cross-chassis LAG interfaces." "form a cross-chassis LAG interfaces."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1201 netbox/vpn/models/l2vpn.py:42 #: netbox/dcim/models/devices.py:1207 netbox/vpn/models/l2vpn.py:42
msgid "identifier" msgid "identifier"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1202 #: netbox/dcim/models/devices.py:1208
msgid "Numeric identifier unique to the parent device" msgid "Numeric identifier unique to the parent device"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1230 netbox/extras/models/customfields.py:231 #: netbox/dcim/models/devices.py:1236 netbox/extras/models/customfields.py:231
#: netbox/extras/models/models.py:111 netbox/extras/models/models.py:800 #: netbox/extras/models/models.py:111 netbox/extras/models/models.py:800
#: netbox/netbox/models/__init__.py:120 netbox/netbox/models/__init__.py:155 #: netbox/netbox/models/__init__.py:120 netbox/netbox/models/__init__.py:155
msgid "comments" msgid "comments"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1246 #: netbox/dcim/models/devices.py:1252
msgid "virtual device context" msgid "virtual device context"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1247 #: netbox/dcim/models/devices.py:1253
msgid "virtual device contexts" msgid "virtual device contexts"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1276 #: netbox/dcim/models/devices.py:1282
#, python-brace-format #, python-brace-format
msgid "{ip} is not an IPv{family} address." msgid "{ip} is not an IPv{family} address."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1282 #: netbox/dcim/models/devices.py:1288
msgid "Primary IP address must belong to an interface on the assigned device." msgid "Primary IP address must belong to an interface on the assigned device."
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1313 #: netbox/dcim/models/devices.py:1319
msgid "MAC addresses" msgid "MAC addresses"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1345 #: netbox/dcim/models/devices.py:1351
msgid "" msgid ""
"Cannot unassign MAC Address while it is designated as the primary MAC for an " "Cannot unassign MAC Address while it is designated as the primary MAC for an "
"object" "object"
msgstr "" msgstr ""
#: netbox/dcim/models/devices.py:1349 #: netbox/dcim/models/devices.py:1355
msgid "" msgid ""
"Cannot reassign MAC Address while it is designated as the primary MAC for an " "Cannot reassign MAC Address while it is designated as the primary MAC for an "
"object" "object"
@ -7378,91 +7378,91 @@ msgstr ""
msgid "The following units have already been reserved: {unit_list}" msgid "The following units have already been reserved: {unit_list}"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:54 #: netbox/dcim/models/sites.py:56
msgid "A top-level region with this name already exists." msgid "A top-level region with this name already exists."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:64 #: netbox/dcim/models/sites.py:66
msgid "A top-level region with this slug already exists." msgid "A top-level region with this slug already exists."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:67 #: netbox/dcim/models/sites.py:69
msgid "region" msgid "region"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:68 #: netbox/dcim/models/sites.py:70
msgid "regions" msgid "regions"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:110 #: netbox/dcim/models/sites.py:112
msgid "A top-level site group with this name already exists." msgid "A top-level site group with this name already exists."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:120 #: netbox/dcim/models/sites.py:122
msgid "A top-level site group with this slug already exists." msgid "A top-level site group with this slug already exists."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:123 #: netbox/dcim/models/sites.py:125
msgid "site group" msgid "site group"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:124 #: netbox/dcim/models/sites.py:126
msgid "site groups" msgid "site groups"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:146 #: netbox/dcim/models/sites.py:148
msgid "Full name of the site" msgid "Full name of the site"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:182 netbox/dcim/models/sites.py:286 #: netbox/dcim/models/sites.py:184 netbox/dcim/models/sites.py:294
msgid "facility" msgid "facility"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:185 netbox/dcim/models/sites.py:289 #: netbox/dcim/models/sites.py:187 netbox/dcim/models/sites.py:297
msgid "Local facility ID or description" msgid "Local facility ID or description"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:197 #: netbox/dcim/models/sites.py:199
msgid "physical address" msgid "physical address"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:200 #: netbox/dcim/models/sites.py:202
msgid "Physical location of the building" msgid "Physical location of the building"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:203 #: netbox/dcim/models/sites.py:205
msgid "shipping address" msgid "shipping address"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:206 #: netbox/dcim/models/sites.py:208
msgid "If different from the physical address" msgid "If different from the physical address"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:248 #: netbox/dcim/models/sites.py:256
msgid "site" msgid "site"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:249 #: netbox/dcim/models/sites.py:257
msgid "sites" msgid "sites"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:322 #: netbox/dcim/models/sites.py:330
msgid "A location with this name already exists within the specified site." msgid "A location with this name already exists within the specified site."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:332 #: netbox/dcim/models/sites.py:340
msgid "A location with this slug already exists within the specified site." msgid "A location with this slug already exists within the specified site."
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:335 #: netbox/dcim/models/sites.py:343
msgid "location" msgid "location"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:336 #: netbox/dcim/models/sites.py:344
msgid "locations" msgid "locations"
msgstr "" msgstr ""
#: netbox/dcim/models/sites.py:347 #: netbox/dcim/models/sites.py:355
#, python-brace-format #, python-brace-format
msgid "Parent location ({parent}) must belong to the same site ({site})." msgid "Parent location ({parent}) must belong to the same site ({site})."
msgstr "" msgstr ""
@ -8985,19 +8985,19 @@ msgstr ""
msgid "Interval at which this script is re-run (in minutes)" msgid "Interval at which this script is re-run (in minutes)"
msgstr "" msgstr ""
#: netbox/extras/jobs.py:50 #: netbox/extras/jobs.py:64
msgid "Database changes have been reverted automatically." msgid "Database changes have been reverted automatically."
msgstr "" msgstr ""
#: netbox/extras/jobs.py:56 #: netbox/extras/jobs.py:70
msgid "Script aborted with error: " msgid "Script aborted with error: "
msgstr "" msgstr ""
#: netbox/extras/jobs.py:67 #: netbox/extras/jobs.py:81
msgid "An exception occurred: " msgid "An exception occurred: "
msgstr "" msgstr ""
#: netbox/extras/jobs.py:73 #: netbox/extras/jobs.py:87
msgid "Database changes have been reverted due to error." msgid "Database changes have been reverted due to error."
msgstr "" msgstr ""