mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-22 03:28:45 -06:00
Compare commits
7 Commits
2a27e475e4
...
v4.3.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6eeb382512 | ||
|
|
e5d6c71171 | ||
|
|
f777bfee2e | ||
|
|
8b63eb64c1 | ||
|
|
cff29f9551 | ||
|
|
a5c0cae112 | ||
|
|
23cc4f1c41 |
@@ -15,7 +15,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: NetBox version
|
label: NetBox version
|
||||||
description: What version of NetBox are you currently running?
|
description: What version of NetBox are you currently running?
|
||||||
placeholder: v4.3.3
|
placeholder: v4.3.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
|||||||
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
@@ -27,7 +27,7 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: NetBox Version
|
label: NetBox Version
|
||||||
description: What version of NetBox are you currently running?
|
description: What version of NetBox are you currently running?
|
||||||
placeholder: v4.3.3
|
placeholder: v4.3.4
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ django-debug-toolbar
|
|||||||
# https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst
|
# https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst
|
||||||
django-filter
|
django-filter
|
||||||
|
|
||||||
|
# Django Debug Toolbar extension for GraphiQL
|
||||||
|
# https://github.com/flavors/django-graphiql-debug-toolbar/blob/main/CHANGES.rst
|
||||||
|
django-graphiql-debug-toolbar
|
||||||
|
|
||||||
# HTMX utilities for Django
|
# HTMX utilities for Django
|
||||||
# https://django-htmx.readthedocs.io/en/latest/changelog.html
|
# https://django-htmx.readthedocs.io/en/latest/changelog.html
|
||||||
django-htmx
|
django-htmx
|
||||||
@@ -108,6 +112,7 @@ nh3
|
|||||||
|
|
||||||
# Fork of PIL (Python Imaging Library) for image processing
|
# Fork of PIL (Python Imaging Library) for image processing
|
||||||
# https://github.com/python-pillow/Pillow/releases
|
# https://github.com/python-pillow/Pillow/releases
|
||||||
|
# https://pillow.readthedocs.io/en/stable/releasenotes/
|
||||||
Pillow
|
Pillow
|
||||||
|
|
||||||
# PostgreSQL database adapter for Python
|
# PostgreSQL database adapter for Python
|
||||||
@@ -126,14 +131,14 @@ requests
|
|||||||
# https://github.com/rq/rq/blob/master/CHANGES.md
|
# https://github.com/rq/rq/blob/master/CHANGES.md
|
||||||
rq
|
rq
|
||||||
|
|
||||||
# Social authentication framework
|
|
||||||
# https://github.com/python-social-auth/social-core/blob/master/CHANGELOG.md
|
|
||||||
social-auth-core
|
|
||||||
|
|
||||||
# Django app for social-auth-core
|
# Django app for social-auth-core
|
||||||
# https://github.com/python-social-auth/social-app-django/blob/master/CHANGELOG.md
|
# https://github.com/python-social-auth/social-app-django/blob/master/CHANGELOG.md
|
||||||
social-auth-app-django
|
social-auth-app-django
|
||||||
|
|
||||||
|
# Social authentication framework
|
||||||
|
# https://github.com/python-social-auth/social-core/blob/master/CHANGELOG.md
|
||||||
|
social-auth-core
|
||||||
|
|
||||||
# Strawberry GraphQL
|
# Strawberry GraphQL
|
||||||
# https://github.com/strawberry-graphql/strawberry/blob/main/CHANGELOG.md
|
# https://github.com/strawberry-graphql/strawberry/blob/main/CHANGELOG.md
|
||||||
strawberry-graphql
|
strawberry-graphql
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ LOGGING = {
|
|||||||
* `netbox.<app>.<model>` - Generic form for model-specific log messages
|
* `netbox.<app>.<model>` - Generic form for model-specific log messages
|
||||||
* `netbox.auth.*` - Authentication events
|
* `netbox.auth.*` - Authentication events
|
||||||
* `netbox.api.views.*` - Views which handle business logic for the REST API
|
* `netbox.api.views.*` - Views which handle business logic for the REST API
|
||||||
|
* `netbox.event_rules` - Event rules
|
||||||
* `netbox.reports.*` - Report execution (`module.name`)
|
* `netbox.reports.*` - Report execution (`module.name`)
|
||||||
* `netbox.scripts.*` - Custom script execution (`module.name`)
|
* `netbox.scripts.*` - Custom script execution (`module.name`)
|
||||||
* `netbox.views.*` - Views which handle business logic for the web UI
|
* `netbox.views.*` - Views which handle business logic for the web UI
|
||||||
|
|||||||
@@ -1,5 +1,27 @@
|
|||||||
# NetBox v4.3
|
# NetBox v4.3
|
||||||
|
|
||||||
|
## v4.3.4 (2025-07-15)
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
|
||||||
|
* [#18811](https://github.com/netbox-community/netbox/issues/18811) - Match expanded form IPv6 addresses in global search
|
||||||
|
* [#19550](https://github.com/netbox-community/netbox/issues/19550) - Enable lazy loading for rack elevations
|
||||||
|
* [#19571](https://github.com/netbox-community/netbox/issues/19571) - Add a default module type profile for expansion cards
|
||||||
|
* [#19793](https://github.com/netbox-community/netbox/issues/19793) - Support custom dynamic navigation menu links
|
||||||
|
* [#19828](https://github.com/netbox-community/netbox/issues/19828) - Expose L2VPN termination in interface GraphQL response
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* [#19413](https://github.com/netbox-community/netbox/issues/19413) - Custom fields should be grouped in filter forms
|
||||||
|
* [#19633](https://github.com/netbox-community/netbox/issues/19633) - Introduce InvalidCondition exception and log all evaluations of invalid event rule conditions
|
||||||
|
* [#19800](https://github.com/netbox-community/netbox/issues/19800) - Module type bulk import should support profile assignment
|
||||||
|
* [#19806](https://github.com/netbox-community/netbox/issues/19806) - Introduce JobFailed exception to allow marking background jobs as failed
|
||||||
|
* [#19827](https://github.com/netbox-community/netbox/issues/19827) - Enforce uniqueness for device role names & slugs
|
||||||
|
* [#19839](https://github.com/netbox-community/netbox/issues/19839) - Enable export of parent assignment for recursively nested objects
|
||||||
|
* [#19876](https://github.com/netbox-community/netbox/issues/19876) - Remove Markdown rendering from CustomFieldChoiceSet description field
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## v4.3.3 (2025-06-26)
|
## v4.3.3 (2025-06-26)
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ class DeviceRoleTable(NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
device_count = columns.LinkedCountColumn(
|
device_count = columns.LinkedCountColumn(
|
||||||
viewname='dcim:device_list',
|
viewname='dcim:device_list',
|
||||||
url_params={'role_id': 'pk'},
|
url_params={'role_id': 'pk'},
|
||||||
@@ -88,8 +92,8 @@ class DeviceRoleTable(NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = models.DeviceRole
|
model = models.DeviceRole
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template', 'description',
|
'pk', 'id', 'name', 'parent', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template',
|
||||||
'slug', 'tags', 'actions', 'created', 'last_updated',
|
'description', 'slug', 'tags', 'actions', 'created', 'last_updated',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description')
|
default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description')
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ class RegionTable(ContactsColumnMixin, NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
site_count = columns.LinkedCountColumn(
|
site_count = columns.LinkedCountColumn(
|
||||||
viewname='dcim:site_list',
|
viewname='dcim:site_list',
|
||||||
url_params={'region_id': 'pk'},
|
url_params={'region_id': 'pk'},
|
||||||
@@ -39,7 +43,7 @@ class RegionTable(ContactsColumnMixin, NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = Region
|
model = Region
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
||||||
'created', 'last_updated', 'actions',
|
'created', 'last_updated', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'site_count', 'description')
|
default_columns = ('pk', 'name', 'site_count', 'description')
|
||||||
@@ -54,6 +58,10 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
site_count = columns.LinkedCountColumn(
|
site_count = columns.LinkedCountColumn(
|
||||||
viewname='dcim:site_list',
|
viewname='dcim:site_list',
|
||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
@@ -69,7 +77,7 @@ class SiteGroupTable(ContactsColumnMixin, NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = SiteGroup
|
model = SiteGroup
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
'pk', 'id', 'name', 'parent', 'slug', 'site_count', 'description', 'comments', 'contacts', 'tags',
|
||||||
'created', 'last_updated', 'actions',
|
'created', 'last_updated', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'site_count', 'description')
|
default_columns = ('pk', 'name', 'site_count', 'description')
|
||||||
@@ -135,6 +143,10 @@ class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
site = tables.Column(
|
site = tables.Column(
|
||||||
verbose_name=_('Site'),
|
verbose_name=_('Site'),
|
||||||
linkify=True
|
linkify=True
|
||||||
@@ -170,8 +182,8 @@ class LocationTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = Location
|
model = Location
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'site', 'status', 'facility', 'tenant', 'tenant_group', 'rack_count', 'device_count',
|
'pk', 'id', 'name', 'parent', 'site', 'status', 'facility', 'tenant', 'tenant_group', 'rack_count',
|
||||||
'description', 'slug', 'comments', 'contacts', 'tags', 'actions', 'created', 'last_updated',
|
'device_count', 'description', 'slug', 'comments', 'contacts', 'tags', 'actions', 'created', 'last_updated',
|
||||||
'vlangroup_count',
|
'vlangroup_count',
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import functools
|
import functools
|
||||||
|
import operator
|
||||||
import re
|
import re
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'Condition',
|
'Condition',
|
||||||
'ConditionSet',
|
'ConditionSet',
|
||||||
|
'InvalidCondition',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
AND = 'and'
|
AND = 'and'
|
||||||
OR = 'or'
|
OR = 'or'
|
||||||
|
|
||||||
@@ -19,6 +20,10 @@ def is_ruleset(data):
|
|||||||
return type(data) is dict and len(data) == 1 and list(data.keys())[0] in (AND, OR)
|
return type(data) is dict and len(data) == 1 and list(data.keys())[0] in (AND, OR)
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidCondition(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Condition:
|
class Condition:
|
||||||
"""
|
"""
|
||||||
An individual conditional rule that evaluates a single attribute and its value.
|
An individual conditional rule that evaluates a single attribute and its value.
|
||||||
@@ -61,6 +66,7 @@ class Condition:
|
|||||||
|
|
||||||
self.attr = attr
|
self.attr = attr
|
||||||
self.value = value
|
self.value = value
|
||||||
|
self.op = op
|
||||||
self.eval_func = getattr(self, f'eval_{op}')
|
self.eval_func = getattr(self, f'eval_{op}')
|
||||||
self.negate = negate
|
self.negate = negate
|
||||||
|
|
||||||
@@ -70,16 +76,17 @@ class Condition:
|
|||||||
"""
|
"""
|
||||||
def _get(obj, key):
|
def _get(obj, key):
|
||||||
if isinstance(obj, list):
|
if isinstance(obj, list):
|
||||||
return [dict.get(i, key) for i in obj]
|
return [operator.getitem(item or {}, key) for item in obj]
|
||||||
|
return operator.getitem(obj or {}, key)
|
||||||
return dict.get(obj, key)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
value = functools.reduce(_get, self.attr.split('.'), data)
|
value = functools.reduce(_get, self.attr.split('.'), data)
|
||||||
except TypeError:
|
except KeyError:
|
||||||
# Invalid key path
|
raise InvalidCondition(f"Invalid key path: {self.attr}")
|
||||||
value = None
|
try:
|
||||||
result = self.eval_func(value)
|
result = self.eval_func(value)
|
||||||
|
except TypeError as e:
|
||||||
|
raise InvalidCondition(f"Invalid data type at '{self.attr}' for '{self.op}' evaluation: {e}")
|
||||||
|
|
||||||
if self.negate:
|
if self.negate:
|
||||||
return not result
|
return not result
|
||||||
|
|||||||
@@ -192,5 +192,5 @@ def flush_events(events):
|
|||||||
try:
|
try:
|
||||||
func = import_string(name)
|
func = import_string(name)
|
||||||
func(events)
|
func(events)
|
||||||
except Exception as e:
|
except ImportError as e:
|
||||||
logger.error(_("Cannot import events pipeline {name} error: {error}").format(name=name, error=e))
|
logger.error(_("Cannot import events pipeline {name} error: {error}").format(name=name, error=e))
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from rest_framework.utils.encoders import JSONEncoder
|
|||||||
|
|
||||||
from core.models import ObjectType
|
from core.models import ObjectType
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.conditions import ConditionSet
|
from extras.conditions import ConditionSet, InvalidCondition
|
||||||
from extras.constants import *
|
from extras.constants import *
|
||||||
from extras.utils import image_upload
|
from extras.utils import image_upload
|
||||||
from extras.models.mixins import RenderTemplateMixin
|
from extras.models.mixins import RenderTemplateMixin
|
||||||
@@ -142,7 +142,15 @@ class EventRule(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLogged
|
|||||||
if not self.conditions:
|
if not self.conditions:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return ConditionSet(self.conditions).eval(data)
|
logger = logging.getLogger('netbox.event_rules')
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = ConditionSet(self.conditions).eval(data)
|
||||||
|
logger.debug(f'{self.name}: Evaluated as {result}')
|
||||||
|
return result
|
||||||
|
except InvalidCondition as e:
|
||||||
|
logger.error(f"{self.name}: Evaluation failed. {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
|
class Webhook(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, ChangeLoggedModel):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from django.test import TestCase
|
|||||||
from core.events import *
|
from core.events import *
|
||||||
from dcim.choices import SiteStatusChoices
|
from dcim.choices import SiteStatusChoices
|
||||||
from dcim.models import Site
|
from dcim.models import Site
|
||||||
from extras.conditions import Condition, ConditionSet
|
from extras.conditions import Condition, ConditionSet, InvalidCondition
|
||||||
from extras.events import serialize_for_event
|
from extras.events import serialize_for_event
|
||||||
from extras.forms import EventRuleForm
|
from extras.forms import EventRuleForm
|
||||||
from extras.models import EventRule, Webhook
|
from extras.models import EventRule, Webhook
|
||||||
@@ -12,16 +12,11 @@ from extras.models import EventRule, Webhook
|
|||||||
|
|
||||||
class ConditionTestCase(TestCase):
|
class ConditionTestCase(TestCase):
|
||||||
|
|
||||||
def test_dotted_path_access(self):
|
|
||||||
c = Condition('a.b.c', 1, 'eq')
|
|
||||||
self.assertTrue(c.eval({'a': {'b': {'c': 1}}}))
|
|
||||||
self.assertFalse(c.eval({'a': {'b': {'c': 2}}}))
|
|
||||||
self.assertFalse(c.eval({'a': {'b': {'x': 1}}}))
|
|
||||||
|
|
||||||
def test_undefined_attr(self):
|
def test_undefined_attr(self):
|
||||||
c = Condition('x', 1, 'eq')
|
c = Condition('x', 1, 'eq')
|
||||||
self.assertFalse(c.eval({}))
|
|
||||||
self.assertTrue(c.eval({'x': 1}))
|
self.assertTrue(c.eval({'x': 1}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({})
|
||||||
|
|
||||||
#
|
#
|
||||||
# Validation tests
|
# Validation tests
|
||||||
@@ -37,10 +32,13 @@ class ConditionTestCase(TestCase):
|
|||||||
# dict type is unsupported
|
# dict type is unsupported
|
||||||
Condition('x', 1, dict())
|
Condition('x', 1, dict())
|
||||||
|
|
||||||
def test_invalid_op_type(self):
|
def test_invalid_op_types(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
# 'gt' supports only numeric values
|
# 'gt' supports only numeric values
|
||||||
Condition('x', 'foo', 'gt')
|
Condition('x', 'foo', 'gt')
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
# 'in' supports only iterable values
|
||||||
|
Condition('x', 123, 'in')
|
||||||
|
|
||||||
#
|
#
|
||||||
# Nested attrs tests
|
# Nested attrs tests
|
||||||
@@ -50,7 +48,10 @@ class ConditionTestCase(TestCase):
|
|||||||
c = Condition('x.y.z', 1)
|
c = Condition('x.y.z', 1)
|
||||||
self.assertTrue(c.eval({'x': {'y': {'z': 1}}}))
|
self.assertTrue(c.eval({'x': {'y': {'z': 1}}}))
|
||||||
self.assertFalse(c.eval({'x': {'y': {'z': 2}}}))
|
self.assertFalse(c.eval({'x': {'y': {'z': 2}}}))
|
||||||
self.assertFalse(c.eval({'a': {'b': {'c': 1}}}))
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': {'y': None}})
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': {'y': {'a': 1}}})
|
||||||
|
|
||||||
#
|
#
|
||||||
# Operator tests
|
# Operator tests
|
||||||
@@ -74,23 +75,31 @@ class ConditionTestCase(TestCase):
|
|||||||
c = Condition('x', 1, 'gt')
|
c = Condition('x', 1, 'gt')
|
||||||
self.assertTrue(c.eval({'x': 2}))
|
self.assertTrue(c.eval({'x': 2}))
|
||||||
self.assertFalse(c.eval({'x': 1}))
|
self.assertFalse(c.eval({'x': 1}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': 'foo'}) # Invalid type
|
||||||
|
|
||||||
def test_gte(self):
|
def test_gte(self):
|
||||||
c = Condition('x', 1, 'gte')
|
c = Condition('x', 1, 'gte')
|
||||||
self.assertTrue(c.eval({'x': 2}))
|
self.assertTrue(c.eval({'x': 2}))
|
||||||
self.assertTrue(c.eval({'x': 1}))
|
self.assertTrue(c.eval({'x': 1}))
|
||||||
self.assertFalse(c.eval({'x': 0}))
|
self.assertFalse(c.eval({'x': 0}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': 'foo'}) # Invalid type
|
||||||
|
|
||||||
def test_lt(self):
|
def test_lt(self):
|
||||||
c = Condition('x', 2, 'lt')
|
c = Condition('x', 2, 'lt')
|
||||||
self.assertTrue(c.eval({'x': 1}))
|
self.assertTrue(c.eval({'x': 1}))
|
||||||
self.assertFalse(c.eval({'x': 2}))
|
self.assertFalse(c.eval({'x': 2}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': 'foo'}) # Invalid type
|
||||||
|
|
||||||
def test_lte(self):
|
def test_lte(self):
|
||||||
c = Condition('x', 2, 'lte')
|
c = Condition('x', 2, 'lte')
|
||||||
self.assertTrue(c.eval({'x': 1}))
|
self.assertTrue(c.eval({'x': 1}))
|
||||||
self.assertTrue(c.eval({'x': 2}))
|
self.assertTrue(c.eval({'x': 2}))
|
||||||
self.assertFalse(c.eval({'x': 3}))
|
self.assertFalse(c.eval({'x': 3}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': 'foo'}) # Invalid type
|
||||||
|
|
||||||
def test_in(self):
|
def test_in(self):
|
||||||
c = Condition('x', [1, 2, 3], 'in')
|
c = Condition('x', [1, 2, 3], 'in')
|
||||||
@@ -106,6 +115,8 @@ class ConditionTestCase(TestCase):
|
|||||||
c = Condition('x', 1, 'contains')
|
c = Condition('x', 1, 'contains')
|
||||||
self.assertTrue(c.eval({'x': [1, 2, 3]}))
|
self.assertTrue(c.eval({'x': [1, 2, 3]}))
|
||||||
self.assertFalse(c.eval({'x': [2, 3, 4]}))
|
self.assertFalse(c.eval({'x': [2, 3, 4]}))
|
||||||
|
with self.assertRaises(InvalidCondition):
|
||||||
|
c.eval({'x': 123}) # Invalid type
|
||||||
|
|
||||||
def test_contains_negated(self):
|
def test_contains_negated(self):
|
||||||
c = Condition('x', 1, 'contains', negate=True)
|
c = Condition('x', 1, 'contains', negate=True)
|
||||||
|
|||||||
2
netbox/project-static/dist/netbox.css
vendored
2
netbox/project-static/dist/netbox.css
vendored
File diff suppressed because one or more lines are too long
10
netbox/project-static/dist/netbox.js
vendored
10
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
4
netbox/project-static/dist/netbox.js.map
vendored
4
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -23,13 +23,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mdi/font": "7.4.47",
|
"@mdi/font": "7.4.47",
|
||||||
"@tabler/core": "1.3.2",
|
"@tabler/core": "1.4.0",
|
||||||
"bootstrap": "5.3.7",
|
"bootstrap": "5.3.7",
|
||||||
"clipboard": "2.0.11",
|
"clipboard": "2.0.11",
|
||||||
"flatpickr": "4.6.13",
|
"flatpickr": "4.6.13",
|
||||||
"gridstack": "12.2.1",
|
"gridstack": "12.2.2",
|
||||||
"htmx.org": "2.0.5",
|
"htmx.org": "2.0.6",
|
||||||
"query-string": "9.2.1",
|
"query-string": "9.2.2",
|
||||||
"sass": "1.89.2",
|
"sass": "1.89.2",
|
||||||
"tom-select": "2.4.3",
|
"tom-select": "2.4.3",
|
||||||
"typeface-inter": "3.18.1",
|
"typeface-inter": "3.18.1",
|
||||||
@@ -39,15 +39,15 @@
|
|||||||
"@types/bootstrap": "5.2.10",
|
"@types/bootstrap": "5.2.10",
|
||||||
"@types/cookie": "^0.6.0",
|
"@types/cookie": "^0.6.0",
|
||||||
"@types/node": "^22.3.0",
|
"@types/node": "^22.3.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.1.0",
|
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
||||||
"@typescript-eslint/parser": "^8.1.0",
|
"@typescript-eslint/parser": "^8.37.0",
|
||||||
"esbuild": "^0.25.3",
|
"esbuild": "^0.25.6",
|
||||||
"esbuild-sass-plugin": "^3.3.1",
|
"esbuild-sass-plugin": "^3.3.1",
|
||||||
"eslint": "<9.0",
|
"eslint": "<9.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-import-resolver-typescript": "^3.6.3",
|
"eslint-import-resolver-typescript": "^3.6.3",
|
||||||
"eslint-plugin-import": "^2.30.0",
|
"eslint-plugin-import": "^2.32.0",
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
"eslint-plugin-prettier": "^5.5.1",
|
||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"typescript": "<5.5"
|
"typescript": "<5.5"
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
|||||||
version: "4.3.3"
|
version: "4.3.4"
|
||||||
edition: "Community"
|
edition: "Community"
|
||||||
published: "2025-06-26"
|
published: "2025-07-15"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Description</th>
|
<th scope="row">Description</th>
|
||||||
<td>{{ object.description|markdown|placeholder }}</td>
|
<td>{{ object.description|placeholder }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Base Choices</th>
|
<th scope="row">Base Choices</th>
|
||||||
|
|||||||
@@ -29,11 +29,7 @@
|
|||||||
<div class="hr-text">
|
<div class="hr-text">
|
||||||
<span>{% trans "Custom Fields" %}</span>
|
<span>{% trans "Custom Fields" %}</span>
|
||||||
</div>
|
</div>
|
||||||
{% for name in filter_form.custom_fields %}
|
{% render_custom_fields filter_form %}
|
||||||
{% with field=filter_form|get_item:name %}
|
|
||||||
{% render_field field %}
|
|
||||||
{% endwith %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ class ContactGroupTable(NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
contact_count = columns.LinkedCountColumn(
|
contact_count = columns.LinkedCountColumn(
|
||||||
viewname='tenancy:contact_list',
|
viewname='tenancy:contact_list',
|
||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
@@ -34,7 +38,7 @@ class ContactGroupTable(NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = ContactGroup
|
model = ContactGroup
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'name', 'contact_count', 'description', 'comments', 'slug', 'tags', 'created',
|
'pk', 'name', 'parent', 'contact_count', 'description', 'comments', 'slug', 'tags', 'created',
|
||||||
'last_updated', 'actions',
|
'last_updated', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'contact_count', 'description')
|
default_columns = ('pk', 'name', 'contact_count', 'description')
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ class TenantGroupTable(NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
tenant_count = columns.LinkedCountColumn(
|
tenant_count = columns.LinkedCountColumn(
|
||||||
viewname='tenancy:tenant_list',
|
viewname='tenancy:tenant_list',
|
||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
@@ -31,7 +35,7 @@ class TenantGroupTable(NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = TenantGroup
|
model = TenantGroup
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'tenant_count', 'description', 'comments', 'slug', 'tags', 'created',
|
'pk', 'id', 'name', 'parent', 'tenant_count', 'description', 'comments', 'slug', 'tags', 'created',
|
||||||
'last_updated', 'actions',
|
'last_updated', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'tenant_count', 'description')
|
default_columns = ('pk', 'name', 'tenant_count', 'description')
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -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-07-09 05:04+0000\n"
|
"POT-Creation-Date: 2025-07-15 05:05+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"
|
||||||
@@ -1461,11 +1461,11 @@ msgstr ""
|
|||||||
#: netbox/core/models/jobs.py:87 netbox/dcim/models/cables.py:49
|
#: netbox/core/models/jobs.py:87 netbox/dcim/models/cables.py:49
|
||||||
#: netbox/dcim/models/device_components.py:456
|
#: netbox/dcim/models/device_components.py:456
|
||||||
#: netbox/dcim/models/device_components.py:1294
|
#: netbox/dcim/models/device_components.py:1294
|
||||||
#: netbox/dcim/models/devices.py:533 netbox/dcim/models/devices.py:1138
|
#: netbox/dcim/models/devices.py:555 netbox/dcim/models/devices.py:1160
|
||||||
#: netbox/dcim/models/modules.py:221 netbox/dcim/models/power.py:94
|
#: netbox/dcim/models/modules.py:221 netbox/dcim/models/power.py:94
|
||||||
#: netbox/dcim/models/racks.py:294 netbox/dcim/models/sites.py:154
|
#: netbox/dcim/models/racks.py:294 netbox/dcim/models/sites.py:154
|
||||||
#: netbox/dcim/models/sites.py:270 netbox/ipam/models/ip.py:237
|
#: netbox/dcim/models/sites.py:270 netbox/ipam/models/ip.py:242
|
||||||
#: netbox/ipam/models/ip.py:511 netbox/ipam/models/ip.py:740
|
#: netbox/ipam/models/ip.py:521 netbox/ipam/models/ip.py:750
|
||||||
#: netbox/ipam/models/vlans.py:217 netbox/virtualization/models/clusters.py:70
|
#: netbox/ipam/models/vlans.py:217 netbox/virtualization/models/clusters.py:70
|
||||||
#: netbox/virtualization/models/virtualmachines.py:79
|
#: netbox/virtualization/models/virtualmachines.py:79
|
||||||
#: netbox/vpn/models/l2vpn.py:36 netbox/vpn/models/tunnels.py:38
|
#: netbox/vpn/models/l2vpn.py:36 netbox/vpn/models/tunnels.py:38
|
||||||
@@ -1592,8 +1592,8 @@ msgstr ""
|
|||||||
#: netbox/circuits/models/providers.py:98 netbox/core/models/data.py:39
|
#: netbox/circuits/models/providers.py:98 netbox/core/models/data.py:39
|
||||||
#: netbox/core/models/jobs.py:48
|
#: netbox/core/models/jobs.py:48
|
||||||
#: netbox/dcim/models/device_component_templates.py:43
|
#: netbox/dcim/models/device_component_templates.py:43
|
||||||
#: netbox/dcim/models/device_components.py:52 netbox/dcim/models/devices.py:477
|
#: netbox/dcim/models/device_components.py:52 netbox/dcim/models/devices.py:499
|
||||||
#: netbox/dcim/models/devices.py:1070 netbox/dcim/models/devices.py:1133
|
#: netbox/dcim/models/devices.py:1092 netbox/dcim/models/devices.py:1155
|
||||||
#: 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:142 netbox/extras/models/configs.py:33
|
#: netbox/dcim/models/sites.py:142 netbox/extras/models/configs.py:33
|
||||||
@@ -1683,8 +1683,8 @@ msgstr ""
|
|||||||
msgid "virtual circuits"
|
msgid "virtual circuits"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/circuits/models/virtual_circuits.py:133 netbox/ipam/models/ip.py:194
|
#: netbox/circuits/models/virtual_circuits.py:133 netbox/ipam/models/ip.py:199
|
||||||
#: netbox/ipam/models/ip.py:747 netbox/vpn/models/tunnels.py:109
|
#: netbox/ipam/models/ip.py:757 netbox/vpn/models/tunnels.py:109
|
||||||
msgid "role"
|
msgid "role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -2636,7 +2636,7 @@ msgstr ""
|
|||||||
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:290 netbox/ipam/models/ip.py:492
|
#: netbox/core/models/data.py:290 netbox/ipam/models/ip.py:502
|
||||||
msgid "size"
|
msgid "size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -3645,7 +3645,7 @@ msgstr ""
|
|||||||
#: netbox/dcim/filtersets.py:1164 netbox/dcim/forms/filtersets.py:838
|
#: netbox/dcim/filtersets.py:1164 netbox/dcim/forms/filtersets.py:838
|
||||||
#: netbox/dcim/forms/filtersets.py:1463 netbox/dcim/forms/filtersets.py:1669
|
#: netbox/dcim/forms/filtersets.py:1463 netbox/dcim/forms/filtersets.py:1669
|
||||||
#: netbox/dcim/forms/filtersets.py:1674 netbox/dcim/forms/model_forms.py:1887
|
#: netbox/dcim/forms/filtersets.py:1674 netbox/dcim/forms/model_forms.py:1887
|
||||||
#: netbox/dcim/models/devices.py:1234 netbox/dcim/models/devices.py:1254
|
#: netbox/dcim/models/devices.py:1256 netbox/dcim/models/devices.py:1276
|
||||||
#: netbox/virtualization/filtersets.py:198
|
#: netbox/virtualization/filtersets.py:198
|
||||||
#: netbox/virtualization/filtersets.py:270
|
#: netbox/virtualization/filtersets.py:270
|
||||||
#: netbox/virtualization/forms/filtersets.py:178
|
#: netbox/virtualization/forms/filtersets.py:178
|
||||||
@@ -3806,8 +3806,8 @@ msgstr ""
|
|||||||
#: netbox/ipam/forms/model_forms.py:208 netbox/ipam/forms/model_forms.py:256
|
#: netbox/ipam/forms/model_forms.py:208 netbox/ipam/forms/model_forms.py:256
|
||||||
#: netbox/ipam/forms/model_forms.py:310 netbox/ipam/forms/model_forms.py:474
|
#: netbox/ipam/forms/model_forms.py:310 netbox/ipam/forms/model_forms.py:474
|
||||||
#: netbox/ipam/forms/model_forms.py:488 netbox/ipam/forms/model_forms.py:502
|
#: netbox/ipam/forms/model_forms.py:488 netbox/ipam/forms/model_forms.py:502
|
||||||
#: netbox/ipam/models/ip.py:217 netbox/ipam/models/ip.py:501
|
#: netbox/ipam/models/ip.py:222 netbox/ipam/models/ip.py:511
|
||||||
#: netbox/ipam/models/ip.py:730 netbox/ipam/models/vrfs.py:61
|
#: netbox/ipam/models/ip.py:740 netbox/ipam/models/vrfs.py:61
|
||||||
#: netbox/ipam/tables/ip.py:189 netbox/ipam/tables/ip.py:262
|
#: netbox/ipam/tables/ip.py:189 netbox/ipam/tables/ip.py:262
|
||||||
#: netbox/ipam/tables/ip.py:318 netbox/ipam/tables/ip.py:418
|
#: netbox/ipam/tables/ip.py:318 netbox/ipam/tables/ip.py:418
|
||||||
#: netbox/templates/dcim/interface.html:152
|
#: netbox/templates/dcim/interface.html:152
|
||||||
@@ -5417,7 +5417,7 @@ msgstr ""
|
|||||||
msgid "Device Role"
|
msgid "Device Role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/forms/model_forms.py:594 netbox/dcim/models/devices.py:523
|
#: netbox/dcim/forms/model_forms.py:594 netbox/dcim/models/devices.py:545
|
||||||
msgid "The lowest-numbered unit occupied by the device"
|
msgid "The lowest-numbered unit occupied by the device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -6391,14 +6391,14 @@ msgid "inventory item roles"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/device_components.py:1321
|
#: netbox/dcim/models/device_components.py:1321
|
||||||
#: netbox/dcim/models/devices.py:486 netbox/dcim/models/modules.py:229
|
#: netbox/dcim/models/devices.py:508 netbox/dcim/models/modules.py:229
|
||||||
#: netbox/dcim/models/racks.py:310
|
#: netbox/dcim/models/racks.py:310
|
||||||
#: netbox/virtualization/models/virtualmachines.py:125
|
#: netbox/virtualization/models/virtualmachines.py:125
|
||||||
msgid "serial number"
|
msgid "serial number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/device_components.py:1329
|
#: netbox/dcim/models/device_components.py:1329
|
||||||
#: netbox/dcim/models/devices.py:494 netbox/dcim/models/modules.py:236
|
#: netbox/dcim/models/devices.py:516 netbox/dcim/models/modules.py:236
|
||||||
#: netbox/dcim/models/racks.py:317
|
#: netbox/dcim/models/racks.py:317
|
||||||
msgid "asset tag"
|
msgid "asset tag"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -6494,7 +6494,7 @@ msgid ""
|
|||||||
"device type is neither a parent nor a child."
|
"device type is neither a parent nor a child."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:131 netbox/dcim/models/devices.py:539
|
#: netbox/dcim/models/devices.py:131 netbox/dcim/models/devices.py:561
|
||||||
#: netbox/dcim/models/modules.py:95 netbox/dcim/models/racks.py:321
|
#: netbox/dcim/models/modules.py:95 netbox/dcim/models/racks.py:321
|
||||||
msgid "airflow"
|
msgid "airflow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -6539,261 +6539,269 @@ msgstr ""
|
|||||||
msgid "Virtual machines may be assigned to this role"
|
msgid "Virtual machines may be assigned to this role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:401
|
#: netbox/dcim/models/devices.py:410
|
||||||
|
msgid "A top-level device role with this name already exists."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: netbox/dcim/models/devices.py:420
|
||||||
|
msgid "A top-level device role with this slug already exists."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: netbox/dcim/models/devices.py:423
|
||||||
msgid "device role"
|
msgid "device role"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:402
|
#: netbox/dcim/models/devices.py:424
|
||||||
msgid "device roles"
|
msgid "device roles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:416
|
#: netbox/dcim/models/devices.py:438
|
||||||
msgid "Optionally limit this platform to devices of a certain manufacturer"
|
msgid "Optionally limit this platform to devices of a certain manufacturer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:428
|
#: netbox/dcim/models/devices.py:450
|
||||||
msgid "platform"
|
msgid "platform"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:429
|
#: netbox/dcim/models/devices.py:451
|
||||||
msgid "platforms"
|
msgid "platforms"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:460
|
#: netbox/dcim/models/devices.py:482
|
||||||
msgid "The function this device serves"
|
msgid "The function this device serves"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:487
|
#: netbox/dcim/models/devices.py:509
|
||||||
msgid "Chassis serial number, assigned by the manufacturer"
|
msgid "Chassis serial number, assigned by the manufacturer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:495 netbox/dcim/models/modules.py:237
|
#: netbox/dcim/models/devices.py:517 netbox/dcim/models/modules.py:237
|
||||||
msgid "A unique tag used to identify this device"
|
msgid "A unique tag used to identify this device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:522
|
#: netbox/dcim/models/devices.py:544
|
||||||
msgid "position (U)"
|
msgid "position (U)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:530
|
#: netbox/dcim/models/devices.py:552
|
||||||
msgid "rack face"
|
msgid "rack face"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:551 netbox/dcim/models/devices.py:1154
|
#: netbox/dcim/models/devices.py:573 netbox/dcim/models/devices.py:1176
|
||||||
#: 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:559 netbox/dcim/models/devices.py:1162
|
#: netbox/dcim/models/devices.py:581 netbox/dcim/models/devices.py:1184
|
||||||
#: netbox/virtualization/models/virtualmachines.py:102
|
#: netbox/virtualization/models/virtualmachines.py:102
|
||||||
msgid "primary IPv6"
|
msgid "primary IPv6"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:567
|
#: netbox/dcim/models/devices.py:589
|
||||||
msgid "out-of-band IP"
|
msgid "out-of-band IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:584
|
#: netbox/dcim/models/devices.py:606
|
||||||
msgid "VC position"
|
msgid "VC position"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:587
|
#: netbox/dcim/models/devices.py:609
|
||||||
msgid "Virtual chassis position"
|
msgid "Virtual chassis position"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:590
|
#: netbox/dcim/models/devices.py:612
|
||||||
msgid "VC priority"
|
msgid "VC priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:594
|
#: netbox/dcim/models/devices.py:616
|
||||||
msgid "Virtual chassis master election priority"
|
msgid "Virtual chassis master election priority"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:597 netbox/dcim/models/sites.py:208
|
#: netbox/dcim/models/devices.py:619 netbox/dcim/models/sites.py:208
|
||||||
msgid "latitude"
|
msgid "latitude"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:602 netbox/dcim/models/devices.py:610
|
#: netbox/dcim/models/devices.py:624 netbox/dcim/models/devices.py:632
|
||||||
#: netbox/dcim/models/sites.py:213 netbox/dcim/models/sites.py:221
|
#: netbox/dcim/models/sites.py:213 netbox/dcim/models/sites.py:221
|
||||||
msgid "GPS coordinate in decimal format (xx.yyyyyy)"
|
msgid "GPS coordinate in decimal format (xx.yyyyyy)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:605 netbox/dcim/models/sites.py:216
|
#: netbox/dcim/models/devices.py:627 netbox/dcim/models/sites.py:216
|
||||||
msgid "longitude"
|
msgid "longitude"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:684
|
#: netbox/dcim/models/devices.py:706
|
||||||
msgid "Device name must be unique per site."
|
msgid "Device name must be unique per site."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:695
|
#: netbox/dcim/models/devices.py:717
|
||||||
msgid "device"
|
msgid "device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:696
|
#: netbox/dcim/models/devices.py:718
|
||||||
msgid "devices"
|
msgid "devices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:715
|
#: netbox/dcim/models/devices.py:737
|
||||||
#, 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:720
|
#: netbox/dcim/models/devices.py:742
|
||||||
#, 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:726
|
#: netbox/dcim/models/devices.py:748
|
||||||
#, 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:733
|
#: netbox/dcim/models/devices.py:755
|
||||||
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:737
|
#: netbox/dcim/models/devices.py:759
|
||||||
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:743
|
#: netbox/dcim/models/devices.py:765
|
||||||
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:747
|
#: netbox/dcim/models/devices.py:769
|
||||||
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:755
|
#: netbox/dcim/models/devices.py:777
|
||||||
#, 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:766
|
#: netbox/dcim/models/devices.py:788
|
||||||
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:773
|
#: netbox/dcim/models/devices.py:795
|
||||||
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:787
|
#: netbox/dcim/models/devices.py:809
|
||||||
#, 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:802
|
#: netbox/dcim/models/devices.py:824
|
||||||
#, 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:814 netbox/dcim/models/devices.py:832
|
#: netbox/dcim/models/devices.py:836 netbox/dcim/models/devices.py:854
|
||||||
#, 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:820
|
#: netbox/dcim/models/devices.py:842
|
||||||
#, 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:850
|
#: netbox/dcim/models/devices.py:872
|
||||||
#, 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:861
|
#: netbox/dcim/models/devices.py:883
|
||||||
#, 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:868
|
#: netbox/dcim/models/devices.py:890
|
||||||
#, 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:876
|
#: netbox/dcim/models/devices.py:898
|
||||||
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:882
|
#: netbox/dcim/models/devices.py:904
|
||||||
#, 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:1075
|
#: netbox/dcim/models/devices.py:1097
|
||||||
msgid "domain"
|
msgid "domain"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1088 netbox/dcim/models/devices.py:1089
|
#: netbox/dcim/models/devices.py:1110 netbox/dcim/models/devices.py:1111
|
||||||
msgid "virtual chassis"
|
msgid "virtual chassis"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1101
|
#: netbox/dcim/models/devices.py:1123
|
||||||
#, 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:1117
|
#: netbox/dcim/models/devices.py:1139
|
||||||
#, 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:1143 netbox/vpn/models/l2vpn.py:42
|
#: netbox/dcim/models/devices.py:1165 netbox/vpn/models/l2vpn.py:42
|
||||||
msgid "identifier"
|
msgid "identifier"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1144
|
#: netbox/dcim/models/devices.py:1166
|
||||||
msgid "Numeric identifier unique to the parent device"
|
msgid "Numeric identifier unique to the parent device"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1172 netbox/extras/models/customfields.py:227
|
#: netbox/dcim/models/devices.py:1194 netbox/extras/models/customfields.py:227
|
||||||
#: netbox/extras/models/models.py:109 netbox/extras/models/models.py:767
|
#: netbox/extras/models/models.py:109 netbox/extras/models/models.py:767
|
||||||
#: 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:1188
|
#: netbox/dcim/models/devices.py:1210
|
||||||
msgid "virtual device context"
|
msgid "virtual device context"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1189
|
#: netbox/dcim/models/devices.py:1211
|
||||||
msgid "virtual device contexts"
|
msgid "virtual device contexts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1218
|
#: netbox/dcim/models/devices.py:1240
|
||||||
#, 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:1224
|
#: netbox/dcim/models/devices.py:1246
|
||||||
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:1255
|
#: netbox/dcim/models/devices.py:1277
|
||||||
msgid "MAC addresses"
|
msgid "MAC addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/dcim/models/devices.py:1287
|
#: netbox/dcim/models/devices.py:1309
|
||||||
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:1291
|
#: netbox/dcim/models/devices.py:1313
|
||||||
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"
|
||||||
@@ -8656,7 +8664,7 @@ msgstr ""
|
|||||||
#: netbox/extras/models/configs.py:38 netbox/extras/models/models.py:315
|
#: netbox/extras/models/configs.py:38 netbox/extras/models/models.py:315
|
||||||
#: netbox/extras/models/models.py:480 netbox/extras/models/models.py:559
|
#: netbox/extras/models/models.py:480 netbox/extras/models/models.py:559
|
||||||
#: netbox/extras/models/search.py:48 netbox/extras/models/tags.py:44
|
#: netbox/extras/models/search.py:48 netbox/extras/models/tags.py:44
|
||||||
#: netbox/ipam/models/ip.py:188 netbox/netbox/models/mixins.py:16
|
#: netbox/ipam/models/ip.py:193 netbox/netbox/models/mixins.py:16
|
||||||
msgid "weight"
|
msgid "weight"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -9903,7 +9911,7 @@ msgstr ""
|
|||||||
msgid "IP address (ID)"
|
msgid "IP address (ID)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/filtersets.py:1205 netbox/ipam/models/ip.py:798
|
#: netbox/ipam/filtersets.py:1205 netbox/ipam/models/ip.py:808
|
||||||
msgid "IP address"
|
msgid "IP address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -10012,7 +10020,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: netbox/ipam/forms/bulk_edit.py:257 netbox/ipam/forms/bulk_edit.py:307
|
#: netbox/ipam/forms/bulk_edit.py:257 netbox/ipam/forms/bulk_edit.py:307
|
||||||
#: netbox/ipam/forms/filtersets.py:258 netbox/ipam/forms/filtersets.py:316
|
#: netbox/ipam/forms/filtersets.py:258 netbox/ipam/forms/filtersets.py:316
|
||||||
#: netbox/ipam/models/ip.py:256
|
#: netbox/ipam/models/ip.py:261
|
||||||
msgid "Treat as fully utilized"
|
msgid "Treat as fully utilized"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -10025,7 +10033,7 @@ msgstr ""
|
|||||||
msgid "Treat as populated"
|
msgid "Treat as populated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/forms/bulk_edit.py:355 netbox/ipam/models/ip.py:782
|
#: netbox/ipam/forms/bulk_edit.py:355 netbox/ipam/models/ip.py:792
|
||||||
msgid "DNS name"
|
msgid "DNS name"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -10532,185 +10540,185 @@ msgid ""
|
|||||||
"({aggregate})."
|
"({aggregate})."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:195
|
#: netbox/ipam/models/ip.py:200
|
||||||
msgid "roles"
|
msgid "roles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:208 netbox/ipam/models/ip.py:277
|
#: netbox/ipam/models/ip.py:213 netbox/ipam/models/ip.py:282
|
||||||
msgid "prefix"
|
msgid "prefix"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:209
|
#: netbox/ipam/models/ip.py:214
|
||||||
msgid "IPv4 or IPv6 network with mask"
|
msgid "IPv4 or IPv6 network with mask"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:238
|
#: netbox/ipam/models/ip.py:243
|
||||||
msgid "Operational status of this prefix"
|
msgid "Operational status of this prefix"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:246
|
#: netbox/ipam/models/ip.py:251
|
||||||
msgid "The primary function of this prefix"
|
msgid "The primary function of this prefix"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:249
|
#: netbox/ipam/models/ip.py:254
|
||||||
msgid "is a pool"
|
msgid "is a pool"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:251
|
#: netbox/ipam/models/ip.py:256
|
||||||
msgid "All IP addresses within this prefix are considered usable"
|
msgid "All IP addresses within this prefix are considered usable"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:254 netbox/ipam/models/ip.py:531
|
#: netbox/ipam/models/ip.py:259 netbox/ipam/models/ip.py:541
|
||||||
msgid "mark utilized"
|
msgid "mark utilized"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:278
|
#: netbox/ipam/models/ip.py:283
|
||||||
msgid "prefixes"
|
msgid "prefixes"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:298
|
#: netbox/ipam/models/ip.py:303
|
||||||
msgid "Cannot create prefix with /0 mask."
|
msgid "Cannot create prefix with /0 mask."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:305 netbox/ipam/models/ip.py:881
|
#: netbox/ipam/models/ip.py:310 netbox/ipam/models/ip.py:896
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "VRF {vrf}"
|
msgid "VRF {vrf}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:305 netbox/ipam/models/ip.py:881
|
#: netbox/ipam/models/ip.py:310 netbox/ipam/models/ip.py:896
|
||||||
msgid "global table"
|
msgid "global table"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:307
|
#: netbox/ipam/models/ip.py:312
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Duplicate prefix found in {table}: {prefix}"
|
msgid "Duplicate prefix found in {table}: {prefix}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:484
|
#: netbox/ipam/models/ip.py:494
|
||||||
msgid "start address"
|
msgid "start address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:485 netbox/ipam/models/ip.py:489
|
#: netbox/ipam/models/ip.py:495 netbox/ipam/models/ip.py:499
|
||||||
#: netbox/ipam/models/ip.py:722
|
#: netbox/ipam/models/ip.py:732
|
||||||
msgid "IPv4 or IPv6 address (with mask)"
|
msgid "IPv4 or IPv6 address (with mask)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:488
|
#: netbox/ipam/models/ip.py:498
|
||||||
msgid "end address"
|
msgid "end address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:515
|
#: netbox/ipam/models/ip.py:525
|
||||||
msgid "Operational status of this range"
|
msgid "Operational status of this range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:523
|
#: netbox/ipam/models/ip.py:533
|
||||||
msgid "The primary function of this range"
|
msgid "The primary function of this range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:526
|
#: netbox/ipam/models/ip.py:536
|
||||||
msgid "mark populated"
|
msgid "mark populated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:528
|
#: netbox/ipam/models/ip.py:538
|
||||||
msgid "Prevent the creation of IP addresses within this range"
|
msgid "Prevent the creation of IP addresses within this range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:533
|
#: netbox/ipam/models/ip.py:543
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Report space as 100% utilized"
|
msgid "Report space as 100% utilized"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:542
|
#: netbox/ipam/models/ip.py:552
|
||||||
msgid "IP range"
|
msgid "IP range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:543
|
#: netbox/ipam/models/ip.py:553
|
||||||
msgid "IP ranges"
|
msgid "IP ranges"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:556
|
#: netbox/ipam/models/ip.py:566
|
||||||
msgid "Starting and ending IP address versions must match"
|
msgid "Starting and ending IP address versions must match"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:562
|
#: netbox/ipam/models/ip.py:572
|
||||||
msgid "Starting and ending IP address masks must match"
|
msgid "Starting and ending IP address masks must match"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:569
|
#: netbox/ipam/models/ip.py:579
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Ending address must be greater than the starting address ({start_address})"
|
"Ending address must be greater than the starting address ({start_address})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:597
|
#: netbox/ipam/models/ip.py:607
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Defined addresses overlap with range {overlapping_range} in VRF {vrf}"
|
msgid "Defined addresses overlap with range {overlapping_range} in VRF {vrf}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:606
|
#: netbox/ipam/models/ip.py:616
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Defined range exceeds maximum supported size ({max_size})"
|
msgid "Defined range exceeds maximum supported size ({max_size})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:721 netbox/tenancy/models/contacts.py:76
|
#: netbox/ipam/models/ip.py:731 netbox/tenancy/models/contacts.py:76
|
||||||
msgid "address"
|
msgid "address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:744
|
#: netbox/ipam/models/ip.py:754
|
||||||
msgid "The operational status of this IP"
|
msgid "The operational status of this IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:752
|
#: netbox/ipam/models/ip.py:762
|
||||||
msgid "The functional role of this IP"
|
msgid "The functional role of this IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:775 netbox/templates/ipam/ipaddress.html:72
|
#: netbox/ipam/models/ip.py:785 netbox/templates/ipam/ipaddress.html:72
|
||||||
msgid "NAT (inside)"
|
msgid "NAT (inside)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:776
|
#: netbox/ipam/models/ip.py:786
|
||||||
msgid "The IP for which this address is the \"outside\" IP"
|
msgid "The IP for which this address is the \"outside\" IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:783
|
#: netbox/ipam/models/ip.py:793
|
||||||
msgid "Hostname or FQDN (not case-sensitive)"
|
msgid "Hostname or FQDN (not case-sensitive)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:799 netbox/ipam/models/services.py:86
|
#: netbox/ipam/models/ip.py:809 netbox/ipam/models/services.py:86
|
||||||
msgid "IP addresses"
|
msgid "IP addresses"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:852
|
#: netbox/ipam/models/ip.py:867
|
||||||
msgid "Cannot create IP address with /0 mask."
|
msgid "Cannot create IP address with /0 mask."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:858
|
#: netbox/ipam/models/ip.py:873
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{ip} is a network ID, which may not be assigned to an interface."
|
msgid "{ip} is a network ID, which may not be assigned to an interface."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:869
|
#: netbox/ipam/models/ip.py:884
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "{ip} is a broadcast address, which may not be assigned to an interface."
|
msgid "{ip} is a broadcast address, which may not be assigned to an interface."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:883
|
#: netbox/ipam/models/ip.py:898
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Duplicate IP address found in {table}: {ipaddress}"
|
msgid "Duplicate IP address found in {table}: {ipaddress}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:899
|
#: netbox/ipam/models/ip.py:914
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Cannot create IP address {ip} inside range {range}."
|
msgid "Cannot create IP address {ip} inside range {range}."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:920
|
#: netbox/ipam/models/ip.py:935
|
||||||
msgid ""
|
msgid ""
|
||||||
"Cannot reassign IP address while it is designated as the primary IP for the "
|
"Cannot reassign IP address while it is designated as the primary IP for the "
|
||||||
"parent object"
|
"parent object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/ipam/models/ip.py:926
|
#: netbox/ipam/models/ip.py:941
|
||||||
msgid "Only IPv6 addresses can be assigned SLAAC status"
|
msgid "Only IPv6 addresses can be assigned SLAAC status"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -11863,16 +11871,16 @@ msgstr ""
|
|||||||
msgid "Background Tasks"
|
msgid "Background Tasks"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/netbox/plugins/navigation.py:48
|
#: netbox/netbox/plugins/navigation.py:55
|
||||||
#: netbox/netbox/plugins/navigation.py:70
|
#: netbox/netbox/plugins/navigation.py:88
|
||||||
msgid "Permissions must be passed as a tuple or list."
|
msgid "Permissions must be passed as a tuple or list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/netbox/plugins/navigation.py:52
|
#: netbox/netbox/plugins/navigation.py:59
|
||||||
msgid "Buttons must be passed as a tuple or list."
|
msgid "Buttons must be passed as a tuple or list."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: netbox/netbox/plugins/navigation.py:74
|
#: netbox/netbox/plugins/navigation.py:92
|
||||||
msgid "Button color must be a choice within ButtonColorChoices."
|
msgid "Button color must be a choice within ButtonColorChoices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,10 @@ class WirelessLANGroupTable(NetBoxTable):
|
|||||||
verbose_name=_('Name'),
|
verbose_name=_('Name'),
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
|
parent = tables.Column(
|
||||||
|
verbose_name=_('Parent'),
|
||||||
|
linkify=True,
|
||||||
|
)
|
||||||
wirelesslan_count = columns.LinkedCountColumn(
|
wirelesslan_count = columns.LinkedCountColumn(
|
||||||
viewname='wireless:wirelesslan_list',
|
viewname='wireless:wirelesslan_list',
|
||||||
url_params={'group_id': 'pk'},
|
url_params={'group_id': 'pk'},
|
||||||
@@ -33,8 +37,8 @@ class WirelessLANGroupTable(NetBoxTable):
|
|||||||
class Meta(NetBoxTable.Meta):
|
class Meta(NetBoxTable.Meta):
|
||||||
model = WirelessLANGroup
|
model = WirelessLANGroup
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'name', 'wirelesslan_count', 'slug', 'description', 'comments', 'tags', 'created', 'last_updated',
|
'pk', 'name', 'parent', 'slug', 'description', 'comments', 'tags', 'wirelesslan_count', 'created',
|
||||||
'actions',
|
'last_updated', 'actions',
|
||||||
)
|
)
|
||||||
default_columns = ('pk', 'name', 'wirelesslan_count', 'description')
|
default_columns = ('pk', 'name', 'wirelesslan_count', 'description')
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netbox"
|
name = "netbox"
|
||||||
version = "4.3.3"
|
version = "4.3.4"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "NetBox Community" }
|
{ name = "NetBox Community" }
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
Django==5.2.3
|
Django==5.2.4
|
||||||
django-cors-headers==4.7.0
|
django-cors-headers==4.7.0
|
||||||
django-debug-toolbar==5.2.0
|
django-debug-toolbar==5.2.0
|
||||||
django-filter==25.1
|
django-filter==25.1
|
||||||
django-htmx==1.23.1
|
|
||||||
django-graphiql-debug-toolbar==0.2.0
|
django-graphiql-debug-toolbar==0.2.0
|
||||||
|
django-htmx==1.23.2
|
||||||
django-mptt==0.17.0
|
django-mptt==0.17.0
|
||||||
django-pglocks==1.0.4
|
django-pglocks==1.0.4
|
||||||
django-prometheus==2.4.1
|
django-prometheus==2.4.1
|
||||||
@@ -11,29 +11,29 @@ django-redis==6.0.0
|
|||||||
django-rich==2.0.0
|
django-rich==2.0.0
|
||||||
django-rq==3.0.1
|
django-rq==3.0.1
|
||||||
django-storages==1.14.6
|
django-storages==1.14.6
|
||||||
django-taggit==6.1.0
|
|
||||||
django-tables2==2.7.5
|
django-tables2==2.7.5
|
||||||
|
django-taggit==6.1.0
|
||||||
django-timezone-field==7.1
|
django-timezone-field==7.1
|
||||||
djangorestframework==3.16.0
|
djangorestframework==3.16.0
|
||||||
drf-spectacular==0.28.0
|
drf-spectacular==0.28.0
|
||||||
drf-spectacular-sidecar==2025.6.1
|
drf-spectacular-sidecar==2025.7.1
|
||||||
feedparser==6.0.11
|
feedparser==6.0.11
|
||||||
gunicorn==23.0.0
|
gunicorn==23.0.0
|
||||||
Jinja2==3.1.6
|
Jinja2==3.1.6
|
||||||
jsonschema==4.24.0
|
jsonschema==4.24.0
|
||||||
Markdown==3.8.2
|
Markdown==3.8.2
|
||||||
mkdocs-material==9.6.14
|
mkdocs-material==9.6.15
|
||||||
mkdocstrings[python]==0.29.1
|
mkdocstrings[python]==0.29.1
|
||||||
netaddr==1.3.0
|
netaddr==1.3.0
|
||||||
nh3==0.2.21
|
nh3==0.2.22
|
||||||
Pillow==11.2.1
|
Pillow==11.3.0
|
||||||
psycopg[c,pool]==3.2.9
|
psycopg[c,pool]==3.2.9
|
||||||
PyYAML==6.0.2
|
PyYAML==6.0.2
|
||||||
requests==2.32.4
|
requests==2.32.4
|
||||||
rq==2.4.0
|
rq==2.4.0
|
||||||
social-auth-app-django==5.4.3
|
social-auth-app-django==5.5.1
|
||||||
social-auth-core==4.6.1
|
social-auth-core==4.7.0
|
||||||
strawberry-graphql==0.275.4
|
strawberry-graphql==0.276.0
|
||||||
strawberry-graphql-django==0.60.0
|
strawberry-graphql-django==0.60.0
|
||||||
svgwrite==1.4.3
|
svgwrite==1.4.3
|
||||||
tablib==3.8.0
|
tablib==3.8.0
|
||||||
|
|||||||
Reference in New Issue
Block a user