mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-13 16:47:34 -06:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9c2cd66162 | ||
![]() |
f61a2964c8 | ||
![]() |
ee94fb0b94 | ||
![]() |
8fb8f4c75b | ||
![]() |
e33793dc82 | ||
![]() |
3b8841ee3b | ||
![]() |
ea4c205a37 | ||
![]() |
2a5d3abafb |
@ -6,7 +6,7 @@
|
||||
<a href="https://github.com/netbox-community/netbox/graphs/contributors"><img src="https://img.shields.io/github/contributors/netbox-community/netbox?color=blue" alt="Contributors" /></a>
|
||||
<a href="https://github.com/netbox-community/netbox/stargazers"><img src="https://img.shields.io/github/stars/netbox-community/netbox?style=flat" alt="GitHub stars" /></a>
|
||||
<a href="https://explore.transifex.com/netbox-community/netbox/"><img src="https://img.shields.io/badge/languages-15-blue" alt="Languages supported" /></a>
|
||||
<a href="https://github.com/netbox-community/netbox/actions/workflows/ci.yml"><img src="https://github.com/netbox-community/netbox/workflows/CI/badge.svg?branch=main" alt="CI status" /></a>
|
||||
<a href="https://github.com/netbox-community/netbox/actions/workflows/ci.yml"><img src="https://github.com/netbox-community/netbox/actions/workflows/ci.yml/badge.svg" alt="CI status" /></a>
|
||||
<p>
|
||||
<strong><a href="https://netboxlabs.com/community/">NetBox Community</a></strong> |
|
||||
<strong><a href="https://netboxlabs.com/netbox-cloud/">NetBox Cloud</a></strong> |
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
NetBox includes the ability to execute certain functions as background tasks. These include:
|
||||
|
||||
* [Report](../customization/reports.md) execution
|
||||
* [Custom script](../customization/custom-scripts.md) execution
|
||||
* Synchronization of [remote data sources](../integrations/synchronized-data.md)
|
||||
* Housekeeping tasks
|
||||
|
||||
Additionally, NetBox plugins can enqueue their own background tasks. This is accomplished using the [Job model](../models/core/job.md). Background tasks are executed by the `rqworker` process(es).
|
||||
|
||||
|
@ -135,7 +135,7 @@ Check out the desired release by specifying its tag. For example:
|
||||
|
||||
```
|
||||
cd /opt/netbox && \
|
||||
sudo git fetch && \
|
||||
sudo git fetch --tags && \
|
||||
sudo git checkout v4.2.7
|
||||
```
|
||||
|
||||
|
@ -15,7 +15,6 @@ A background job implements a basic [Job](../../models/core/job.md) executor for
|
||||
```python title="jobs.py"
|
||||
from netbox.jobs import JobRunner
|
||||
|
||||
|
||||
class MyTestJob(JobRunner):
|
||||
class Meta:
|
||||
name = "My Test Job"
|
||||
@ -25,6 +24,8 @@ class MyTestJob(JobRunner):
|
||||
# your logic goes here
|
||||
```
|
||||
|
||||
Completed jobs will have their status updated to "completed" by default, or "errored" if an unhandled exception was raised by the `run()` method. To intentionally mark a job as failed, raise the `core.exceptions.JobFailed` exception. (Note that "failed" differs from "errored" in that a failure may be expected under certain conditions, whereas an error is not.)
|
||||
|
||||
You can schedule the background job from within your code (e.g. from a model's `save()` method or a view) by calling `MyTestJob.enqueue()`. This method passes through all arguments to `Job.enqueue()`. However, no `name` argument must be passed, as the background job name will be used instead.
|
||||
|
||||
!!! tip
|
||||
|
@ -1,9 +1,19 @@
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
|
||||
class SyncError(Exception):
|
||||
pass
|
||||
__all__ = (
|
||||
'IncompatiblePluginError',
|
||||
'JobFailed',
|
||||
'SyncError',
|
||||
)
|
||||
|
||||
|
||||
class IncompatiblePluginError(ImproperlyConfigured):
|
||||
pass
|
||||
|
||||
|
||||
class JobFailed(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class SyncError(Exception):
|
||||
pass
|
||||
|
@ -187,15 +187,14 @@ class Job(models.Model):
|
||||
"""
|
||||
Mark the job as completed, optionally specifying a particular termination status.
|
||||
"""
|
||||
valid_statuses = JobStatusChoices.TERMINAL_STATE_CHOICES
|
||||
if status not in valid_statuses:
|
||||
if status not in JobStatusChoices.TERMINAL_STATE_CHOICES:
|
||||
raise ValueError(
|
||||
_("Invalid status for job termination. Choices are: {choices}").format(
|
||||
choices=', '.join(valid_statuses)
|
||||
choices=', '.join(JobStatusChoices.TERMINAL_STATE_CHOICES)
|
||||
)
|
||||
)
|
||||
|
||||
# Mark the job as completed
|
||||
# Set the job's status and completion time
|
||||
self.status = status
|
||||
if error:
|
||||
self.error = error
|
||||
|
@ -19,7 +19,8 @@ def load_initial_data(apps, schema_editor):
|
||||
'gpu',
|
||||
'hard_disk',
|
||||
'memory',
|
||||
'power_supply'
|
||||
'power_supply',
|
||||
'expansion_card'
|
||||
)
|
||||
|
||||
for name in initial_profiles:
|
||||
|
@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "Expansion card",
|
||||
"schema": {
|
||||
"properties": {
|
||||
"connector_type": {
|
||||
"type": "string",
|
||||
"description": "Connector type e.g. PCIe x4"
|
||||
},
|
||||
"bandwidth": {
|
||||
"type": "integer",
|
||||
"description": "Total Bandwidth for this module"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ from django_pglocks import advisory_lock
|
||||
from rq.timeouts import JobTimeoutException
|
||||
|
||||
from core.choices import JobStatusChoices
|
||||
from core.exceptions import JobFailed
|
||||
from core.models import Job, ObjectType
|
||||
from netbox.constants import ADVISORY_LOCK_KEYS
|
||||
from netbox.registry import registry
|
||||
@ -73,15 +74,21 @@ class JobRunner(ABC):
|
||||
This method is called by the Job Scheduler to handle the execution of all job commands. It will maintain the
|
||||
job's metadata and handle errors. For periodic jobs, a new job is automatically scheduled using its `interval`.
|
||||
"""
|
||||
logger = logging.getLogger('netbox.jobs')
|
||||
|
||||
try:
|
||||
job.start()
|
||||
cls(job).run(*args, **kwargs)
|
||||
job.terminate()
|
||||
|
||||
except JobFailed:
|
||||
logger.warning(f"Job {job} failed")
|
||||
job.terminate(status=JobStatusChoices.STATUS_FAILED)
|
||||
|
||||
except Exception as e:
|
||||
job.terminate(status=JobStatusChoices.STATUS_ERRORED, error=repr(e))
|
||||
if type(e) is JobTimeoutException:
|
||||
logging.error(e)
|
||||
logger.error(e)
|
||||
|
||||
# If the executed job is a periodic job, schedule its next execution at the specified interval.
|
||||
finally:
|
||||
|
@ -7,11 +7,15 @@ from django_rq import get_queue
|
||||
from ..jobs import *
|
||||
from core.models import DataSource, Job
|
||||
from core.choices import JobStatusChoices
|
||||
from core.exceptions import JobFailed
|
||||
from utilities.testing import disable_warnings
|
||||
|
||||
|
||||
class TestJobRunner(JobRunner):
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
pass
|
||||
if kwargs.get('make_fail', False):
|
||||
raise JobFailed()
|
||||
|
||||
|
||||
class JobRunnerTestCase(TestCase):
|
||||
@ -49,6 +53,12 @@ class JobRunnerTest(JobRunnerTestCase):
|
||||
|
||||
self.assertEqual(job.status, JobStatusChoices.STATUS_COMPLETED)
|
||||
|
||||
def test_handle_failed(self):
|
||||
with disable_warnings('netbox.jobs'):
|
||||
job = TestJobRunner.enqueue(immediate=True, make_fail=True)
|
||||
|
||||
self.assertEqual(job.status, JobStatusChoices.STATUS_FAILED)
|
||||
|
||||
def test_handle_errored(self):
|
||||
class ErroredJobRunner(TestJobRunner):
|
||||
EXP = Exception('Test error')
|
||||
|
BIN
netbox/project-static/dist/netbox.css
vendored
BIN
netbox/project-static/dist/netbox.css
vendored
Binary file not shown.
4
netbox/project-static/styles/custom/racks.scss
Normal file
4
netbox/project-static/styles/custom/racks.scss
Normal file
@ -0,0 +1,4 @@
|
||||
.rack-loading-container {
|
||||
min-height: 200px;
|
||||
margin-left: 30px;
|
||||
}
|
@ -27,3 +27,4 @@
|
||||
@import 'custom/markdown';
|
||||
@import 'custom/misc';
|
||||
@import 'custom/notifications';
|
||||
@import 'custom/racks';
|
||||
|
@ -1,6 +1,17 @@
|
||||
{% load i18n %}
|
||||
<div style="margin-left: -30px">
|
||||
<object data="{% url 'dcim-api:rack-elevation' pk=object.pk %}?face={{face}}&render=svg{% if extra_params %}&{{ extra_params }}{% endif %}" class="rack_elevation" aria-label="{% trans "Rack elevation" %}"></object>
|
||||
<div
|
||||
hx-get="{% url 'dcim-api:rack-elevation' pk=object.pk %}?face={{ face }}&render=svg{% if extra_params %}&{{ extra_params }}{% endif %}"
|
||||
hx-trigger="intersect"
|
||||
hx-swap="outerHTML"
|
||||
aria-label="{% trans "Rack elevation" %}"
|
||||
>
|
||||
<div class="d-flex justify-content-center align-items-center rack-loading-container">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">{% trans "Loading..." %}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<a class="btn btn-outline-primary" href="{% url 'dcim-api:rack-elevation' pk=object.pk %}?face={{face}}&render=svg{% if extra_params %}&{{ extra_params }}{% endif %}" hx-boost="false">
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-26 05:02+0000\n"
|
||||
"POT-Creation-Date: 2025-07-09 05:04+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -20,7 +20,7 @@ msgstr ""
|
||||
|
||||
#: netbox/account/tables.py:27 netbox/templates/account/token.html:22
|
||||
#: netbox/templates/users/token.html:17 netbox/users/forms/bulk_import.py:39
|
||||
#: netbox/users/forms/model_forms.py:112
|
||||
#: netbox/users/forms/model_forms.py:113
|
||||
msgid "Key"
|
||||
msgstr ""
|
||||
|
||||
@ -57,7 +57,7 @@ msgstr ""
|
||||
|
||||
#: netbox/account/tables.py:45 netbox/templates/account/token.html:55
|
||||
#: netbox/templates/users/token.html:47 netbox/users/forms/bulk_edit.py:122
|
||||
#: netbox/users/forms/model_forms.py:124
|
||||
#: netbox/users/forms/model_forms.py:125
|
||||
msgid "Allowed IPs"
|
||||
msgstr ""
|
||||
|
||||
@ -705,7 +705,7 @@ msgstr ""
|
||||
#: netbox/dcim/tables/devices.py:852 netbox/dcim/tables/power.py:77
|
||||
#: netbox/dcim/tables/racks.py:141 netbox/extras/forms/bulk_import.py:42
|
||||
#: netbox/extras/tables/tables.py:449 netbox/extras/tables/tables.py:509
|
||||
#: netbox/netbox/tables/tables.py:272 netbox/templates/circuits/circuit.html:30
|
||||
#: netbox/netbox/tables/tables.py:274 netbox/templates/circuits/circuit.html:30
|
||||
#: netbox/templates/circuits/virtualcircuit.html:39
|
||||
#: netbox/templates/circuits/virtualcircuittermination.html:64
|
||||
#: netbox/templates/core/datasource.html:38 netbox/templates/dcim/cable.html:15
|
||||
@ -804,7 +804,7 @@ msgstr ""
|
||||
#: netbox/templates/vpn/l2vpn.html:26 netbox/templates/vpn/tunnel.html:25
|
||||
#: netbox/templates/wireless/wirelesslan.html:22
|
||||
#: netbox/templates/wireless/wirelesslink.html:17
|
||||
#: netbox/users/forms/filtersets.py:32 netbox/users/forms/model_forms.py:194
|
||||
#: netbox/users/forms/filtersets.py:32 netbox/users/forms/model_forms.py:195
|
||||
#: netbox/virtualization/forms/bulk_edit.py:71
|
||||
#: netbox/virtualization/forms/bulk_edit.py:100
|
||||
#: netbox/virtualization/forms/bulk_import.py:55
|
||||
@ -972,7 +972,7 @@ msgstr ""
|
||||
#: netbox/ipam/forms/filtersets.py:406 netbox/ipam/forms/filtersets.py:492
|
||||
#: netbox/ipam/forms/filtersets.py:505 netbox/ipam/forms/filtersets.py:530
|
||||
#: netbox/ipam/forms/filtersets.py:601 netbox/ipam/forms/filtersets.py:619
|
||||
#: netbox/netbox/tables/tables.py:288 netbox/templates/dcim/moduletype.html:68
|
||||
#: netbox/netbox/tables/tables.py:290 netbox/templates/dcim/moduletype.html:68
|
||||
#: netbox/virtualization/forms/filtersets.py:46
|
||||
#: netbox/virtualization/forms/filtersets.py:109
|
||||
#: netbox/virtualization/forms/filtersets.py:204
|
||||
@ -1369,7 +1369,7 @@ msgstr ""
|
||||
#: netbox/templates/extras/configcontext.html:60
|
||||
#: netbox/templates/ipam/ipaddress.html:59
|
||||
#: netbox/templates/ipam/vlan_edit.html:42
|
||||
#: netbox/tenancy/forms/filtersets.py:87 netbox/users/forms/model_forms.py:314
|
||||
#: netbox/tenancy/forms/filtersets.py:87 netbox/users/forms/model_forms.py:315
|
||||
msgid "Assignment"
|
||||
msgstr ""
|
||||
|
||||
@ -2179,7 +2179,7 @@ msgstr ""
|
||||
|
||||
#: netbox/core/data_backends.py:56 netbox/templates/account/base.html:23
|
||||
#: netbox/templates/account/password.html:12
|
||||
#: netbox/users/forms/model_forms.py:170
|
||||
#: netbox/users/forms/model_forms.py:171
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
@ -2231,7 +2231,7 @@ msgstr ""
|
||||
#: netbox/extras/forms/filtersets.py:335 netbox/extras/tables/tables.py:166
|
||||
#: netbox/extras/tables/tables.py:267 netbox/extras/tables/tables.py:300
|
||||
#: netbox/extras/tables/tables.py:459 netbox/netbox/preferences.py:22
|
||||
#: netbox/templates/core/datasource.html:42
|
||||
#: netbox/netbox/preferences.py:61 netbox/templates/core/datasource.html:42
|
||||
#: netbox/templates/dcim/interface.html:61
|
||||
#: netbox/templates/extras/customlink.html:17
|
||||
#: netbox/templates/extras/eventrule.html:17
|
||||
@ -2346,7 +2346,7 @@ msgstr ""
|
||||
#: netbox/templates/users/user.html:4 netbox/templates/users/user.html:12
|
||||
#: netbox/users/filtersets.py:107 netbox/users/filtersets.py:174
|
||||
#: netbox/users/forms/filtersets.py:84 netbox/users/forms/filtersets.py:125
|
||||
#: netbox/users/forms/model_forms.py:155 netbox/users/forms/model_forms.py:192
|
||||
#: netbox/users/forms/model_forms.py:156 netbox/users/forms/model_forms.py:193
|
||||
#: netbox/users/tables.py:19
|
||||
msgid "User"
|
||||
msgstr ""
|
||||
@ -2449,7 +2449,7 @@ msgstr ""
|
||||
|
||||
#: netbox/core/forms/model_forms.py:170 netbox/dcim/forms/filtersets.py:752
|
||||
#: netbox/templates/core/inc/config_data.html:127
|
||||
#: netbox/users/forms/model_forms.py:64
|
||||
#: netbox/users/forms/model_forms.py:65
|
||||
msgid "Miscellaneous"
|
||||
msgstr ""
|
||||
|
||||
@ -2738,12 +2738,12 @@ msgstr ""
|
||||
msgid "Jobs cannot be assigned to this object type ({type})."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/jobs.py:193
|
||||
#: netbox/core/models/jobs.py:192
|
||||
#, python-brace-format
|
||||
msgid "Invalid status for job termination. Choices are: {choices}"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/core/models/jobs.py:235
|
||||
#: netbox/core/models/jobs.py:234
|
||||
msgid ""
|
||||
"enqueue() cannot be called with values for both schedule_at and immediate."
|
||||
msgstr ""
|
||||
@ -2763,7 +2763,7 @@ msgstr ""
|
||||
#: netbox/extras/tables/tables.py:341 netbox/extras/tables/tables.py:373
|
||||
#: netbox/extras/tables/tables.py:453 netbox/extras/tables/tables.py:514
|
||||
#: netbox/extras/tables/tables.py:637 netbox/extras/tables/tables.py:677
|
||||
#: netbox/extras/tables/tables.py:731 netbox/netbox/tables/tables.py:276
|
||||
#: netbox/extras/tables/tables.py:731 netbox/netbox/tables/tables.py:278
|
||||
#: netbox/templates/core/objectchange.html:58
|
||||
#: netbox/templates/extras/eventrule.html:78
|
||||
#: netbox/templates/extras/journalentry.html:18
|
||||
@ -2801,7 +2801,7 @@ msgstr ""
|
||||
#: netbox/core/tables/jobs.py:10 netbox/core/tables/tasks.py:76
|
||||
#: netbox/dcim/tables/devicetypes.py:169 netbox/extras/tables/tables.py:230
|
||||
#: netbox/extras/tables/tables.py:504 netbox/extras/tables/tables.py:702
|
||||
#: netbox/netbox/tables/tables.py:221
|
||||
#: netbox/netbox/tables/tables.py:223
|
||||
#: netbox/templates/dcim/virtualchassis_edit.html:56
|
||||
#: netbox/utilities/forms/forms.py:73 netbox/wireless/tables/wirelesslink.py:16
|
||||
msgid "ID"
|
||||
@ -3381,8 +3381,9 @@ msgid "Three-phase"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/dcim/choices.py:1657 netbox/extras/choices.py:53
|
||||
#: netbox/netbox/preferences.py:21 netbox/templates/extras/customfield.html:78
|
||||
#: netbox/vpn/choices.py:20 netbox/wireless/choices.py:27
|
||||
#: netbox/netbox/preferences.py:21 netbox/netbox/preferences.py:60
|
||||
#: netbox/templates/extras/customfield.html:78 netbox/vpn/choices.py:20
|
||||
#: netbox/wireless/choices.py:27
|
||||
msgid "Disabled"
|
||||
msgstr ""
|
||||
|
||||
@ -8201,7 +8202,7 @@ msgstr ""
|
||||
#: netbox/extras/forms/model_forms.py:254
|
||||
#: netbox/extras/forms/model_forms.py:297
|
||||
#: netbox/extras/forms/model_forms.py:450
|
||||
#: netbox/extras/forms/model_forms.py:567 netbox/users/forms/model_forms.py:276
|
||||
#: netbox/extras/forms/model_forms.py:567 netbox/users/forms/model_forms.py:277
|
||||
msgid "Object types"
|
||||
msgstr ""
|
||||
|
||||
@ -8297,8 +8298,8 @@ msgstr ""
|
||||
#: netbox/extras/forms/bulk_import.py:275
|
||||
#: netbox/extras/forms/model_forms.py:398 netbox/netbox/navigation/menu.py:413
|
||||
#: netbox/templates/extras/notificationgroup.html:41
|
||||
#: netbox/templates/users/group.html:29 netbox/users/forms/model_forms.py:236
|
||||
#: netbox/users/forms/model_forms.py:248 netbox/users/forms/model_forms.py:300
|
||||
#: netbox/templates/users/group.html:29 netbox/users/forms/model_forms.py:237
|
||||
#: netbox/users/forms/model_forms.py:249 netbox/users/forms/model_forms.py:301
|
||||
#: netbox/users/tables.py:102
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
@ -8314,8 +8315,8 @@ msgstr ""
|
||||
#: netbox/templates/tenancy/contact.html:21
|
||||
#: netbox/tenancy/forms/bulk_edit.py:139 netbox/tenancy/forms/filtersets.py:78
|
||||
#: netbox/tenancy/forms/model_forms.py:99 netbox/tenancy/tables/contacts.py:64
|
||||
#: netbox/users/forms/model_forms.py:181 netbox/users/forms/model_forms.py:193
|
||||
#: netbox/users/forms/model_forms.py:305 netbox/users/tables.py:35
|
||||
#: netbox/users/forms/model_forms.py:182 netbox/users/forms/model_forms.py:194
|
||||
#: netbox/users/forms/model_forms.py:306 netbox/users/tables.py:35
|
||||
#: netbox/users/tables.py:106
|
||||
msgid "Groups"
|
||||
msgstr ""
|
||||
@ -10212,7 +10213,7 @@ msgid ""
|
||||
"One of parent or parent_object_id must be included with parent_object_type"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/forms/bulk_import.py:638
|
||||
#: netbox/ipam/forms/bulk_import.py:641
|
||||
#, python-brace-format
|
||||
msgid "{ip} is not assigned to this parent."
|
||||
msgstr ""
|
||||
@ -11834,9 +11835,9 @@ msgstr ""
|
||||
msgid "API Tokens"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/navigation/menu.py:460 netbox/users/forms/model_forms.py:187
|
||||
#: netbox/users/forms/model_forms.py:195 netbox/users/forms/model_forms.py:242
|
||||
#: netbox/users/forms/model_forms.py:249
|
||||
#: netbox/netbox/navigation/menu.py:460 netbox/users/forms/model_forms.py:188
|
||||
#: netbox/users/forms/model_forms.py:196 netbox/users/forms/model_forms.py:243
|
||||
#: netbox/users/forms/model_forms.py:250
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
@ -11959,11 +11960,19 @@ msgstr ""
|
||||
msgid "Where the paginator controls will be displayed relative to a table"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/preferences.py:60
|
||||
#: netbox/netbox/preferences.py:58
|
||||
msgid "Striped table rows"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/preferences.py:63
|
||||
msgid "Render table rows with alternating colors to increase readability"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/preferences.py:68
|
||||
msgid "Data format"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/preferences.py:65
|
||||
#: netbox/netbox/preferences.py:73
|
||||
msgid "The preferred syntax for displaying generic data within the UI"
|
||||
msgstr ""
|
||||
|
||||
@ -12062,12 +12071,12 @@ msgstr ""
|
||||
msgid "No {model_name} found"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/tables/tables.py:281
|
||||
#: netbox/netbox/tables/tables.py:283
|
||||
#: netbox/templates/generic/bulk_import.html:117
|
||||
msgid "Field"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/tables/tables.py:284
|
||||
#: netbox/netbox/tables/tables.py:286
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
|
||||
@ -13012,7 +13021,7 @@ msgid "Cable Trace for %(object_type)s %(object)s"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/templates/dcim/cable_trace.html:24
|
||||
#: netbox/templates/dcim/inc/rack_elevation.html:7
|
||||
#: netbox/templates/dcim/inc/rack_elevation.html:18
|
||||
msgid "Download SVG"
|
||||
msgstr ""
|
||||
|
||||
@ -13415,10 +13424,14 @@ msgstr ""
|
||||
msgid "Descending Units"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/templates/dcim/inc/rack_elevation.html:3
|
||||
#: netbox/templates/dcim/inc/rack_elevation.html:7
|
||||
msgid "Rack elevation"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/templates/dcim/inc/rack_elevation.html:11
|
||||
msgid "Loading..."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/templates/dcim/interface.html:17
|
||||
msgid "Add Child Interface"
|
||||
msgstr ""
|
||||
@ -13716,7 +13729,7 @@ msgstr ""
|
||||
#: netbox/templates/dcim/virtualchassis_add_member.html:27
|
||||
#: netbox/templates/generic/object_edit.html:78
|
||||
#: netbox/templates/users/objectpermission.html:31
|
||||
#: netbox/users/forms/filtersets.py:67 netbox/users/forms/model_forms.py:312
|
||||
#: netbox/users/forms/filtersets.py:67 netbox/users/forms/model_forms.py:313
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
@ -14874,7 +14887,7 @@ msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/templates/users/objectpermission.html:52
|
||||
#: netbox/users/forms/model_forms.py:315
|
||||
#: netbox/users/forms/model_forms.py:316
|
||||
msgid "Constraints"
|
||||
msgstr ""
|
||||
|
||||
@ -15358,60 +15371,60 @@ msgstr ""
|
||||
msgid "Can Delete"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:62
|
||||
#: netbox/users/forms/model_forms.py:63
|
||||
msgid "User Interface"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:114
|
||||
#: netbox/users/forms/model_forms.py:115
|
||||
msgid ""
|
||||
"Keys must be at least 40 characters in length. <strong>Be sure to record "
|
||||
"your key</strong> prior to submitting this form, as it may no longer be "
|
||||
"accessible once the token has been created."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:126
|
||||
#: netbox/users/forms/model_forms.py:127
|
||||
msgid ""
|
||||
"Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for "
|
||||
"no restrictions. Example: <code>10.1.1.0/24,192.168.10.16/32,2001:"
|
||||
"db8:1::/64</code>"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:175
|
||||
#: netbox/users/forms/model_forms.py:176
|
||||
msgid "Confirm password"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:178
|
||||
#: netbox/users/forms/model_forms.py:179
|
||||
msgid "Enter the same password as before, for verification."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:227
|
||||
#: netbox/users/forms/model_forms.py:228
|
||||
msgid "Passwords do not match! Please check your input and try again."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:294
|
||||
#: netbox/users/forms/model_forms.py:295
|
||||
msgid "Additional actions"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:297
|
||||
#: netbox/users/forms/model_forms.py:298
|
||||
msgid "Actions granted in addition to those listed above"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:313
|
||||
#: netbox/users/forms/model_forms.py:314
|
||||
msgid "Objects"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:325
|
||||
#: netbox/users/forms/model_forms.py:326
|
||||
msgid ""
|
||||
"JSON expression of a queryset filter that will return only permitted "
|
||||
"objects. Leave null to match all objects of this type. A list of multiple "
|
||||
"objects will result in a logical OR operation."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:364
|
||||
#: netbox/users/forms/model_forms.py:365
|
||||
msgid "At least one action must be selected."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/users/forms/model_forms.py:382
|
||||
#: netbox/users/forms/model_forms.py:383
|
||||
#, python-brace-format
|
||||
msgid "Invalid filter for {model}: {error}"
|
||||
msgstr ""
|
||||
|
Loading…
Reference in New Issue
Block a user