mirror of
https://github.com/netbox-community/netbox.git
synced 2026-04-06 00:32:08 +02:00
This commit is contained in:
@@ -26,6 +26,7 @@ from tenancy.models import *
|
||||
from users.filterset_mixins import OwnerFilterMixin
|
||||
from users.models import User
|
||||
from utilities.filters import (
|
||||
MultiValueBigNumberFilter,
|
||||
MultiValueCharFilter,
|
||||
MultiValueContentTypeFilter,
|
||||
MultiValueMACAddressFilter,
|
||||
@@ -2175,7 +2176,7 @@ class InterfaceFilterSet(
|
||||
distinct=False,
|
||||
label=_('LAG interface (ID)'),
|
||||
)
|
||||
speed = MultiValueNumberFilter()
|
||||
speed = MultiValueBigNumberFilter(min_value=0)
|
||||
duplex = django_filters.MultipleChoiceFilter(
|
||||
choices=InterfaceDuplexChoices,
|
||||
distinct=False,
|
||||
|
||||
@@ -20,7 +20,13 @@ from netbox.forms.mixins import ChangelogMessageMixin, OwnerMixin
|
||||
from tenancy.models import Tenant
|
||||
from users.models import User
|
||||
from utilities.forms import BulkEditForm, add_blank_choice, form_from_model
|
||||
from utilities.forms.fields import ColorField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField
|
||||
from utilities.forms.fields import (
|
||||
ColorField,
|
||||
DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField,
|
||||
JSONField,
|
||||
PositiveBigIntegerField,
|
||||
)
|
||||
from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups
|
||||
from utilities.forms.widgets import BulkEditNullBooleanSelect, NumberWithOptions
|
||||
from virtualization.models import Cluster
|
||||
@@ -1420,7 +1426,7 @@ class InterfaceBulkEditForm(
|
||||
'device_id': '$device',
|
||||
}
|
||||
)
|
||||
speed = forms.IntegerField(
|
||||
speed = PositiveBigIntegerField(
|
||||
label=_('Speed'),
|
||||
required=False,
|
||||
widget=NumberWithOptions(
|
||||
|
||||
@@ -19,7 +19,7 @@ from tenancy.forms import ContactModelFilterForm, TenancyFilterForm
|
||||
from tenancy.models import Tenant
|
||||
from users.models import User
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice
|
||||
from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, TagFilterField
|
||||
from utilities.forms.fields import ColorField, DynamicModelMultipleChoiceField, PositiveBigIntegerField, TagFilterField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
from utilities.forms.widgets import NumberWithOptions
|
||||
from virtualization.models import Cluster, ClusterGroup, VirtualMachine
|
||||
@@ -1603,7 +1603,7 @@ class InterfaceFilterForm(PathEndpointFilterForm, DeviceComponentFilterForm):
|
||||
choices=InterfaceTypeChoices,
|
||||
required=False
|
||||
)
|
||||
speed = forms.IntegerField(
|
||||
speed = PositiveBigIntegerField(
|
||||
label=_('Speed'),
|
||||
required=False,
|
||||
widget=NumberWithOptions(
|
||||
|
||||
@@ -47,7 +47,13 @@ if TYPE_CHECKING:
|
||||
VRFFilter,
|
||||
)
|
||||
from netbox.graphql.enums import ColorEnum
|
||||
from netbox.graphql.filter_lookups import FloatLookup, IntegerArrayLookup, IntegerLookup, TreeNodeFilter
|
||||
from netbox.graphql.filter_lookups import (
|
||||
BigIntegerLookup,
|
||||
FloatLookup,
|
||||
IntegerArrayLookup,
|
||||
IntegerLookup,
|
||||
TreeNodeFilter,
|
||||
)
|
||||
from users.graphql.filters import UserFilter
|
||||
from virtualization.graphql.filters import ClusterFilter
|
||||
from vpn.graphql.filters import L2VPNFilter, TunnelTerminationFilter
|
||||
@@ -519,7 +525,7 @@ class InterfaceFilter(
|
||||
strawberry_django.filter_field()
|
||||
)
|
||||
mgmt_only: FilterLookup[bool] | None = strawberry_django.filter_field()
|
||||
speed: Annotated['IntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
|
||||
speed: Annotated['BigIntegerLookup', strawberry.lazy('netbox.graphql.filter_lookups')] | None = (
|
||||
strawberry_django.filter_field()
|
||||
)
|
||||
duplex: BaseFilterLookup[Annotated['InterfaceDuplexEnum', strawberry.lazy('dcim.graphql.enums')]] | None = (
|
||||
|
||||
@@ -433,6 +433,7 @@ class MACAddressType(PrimaryObjectType):
|
||||
)
|
||||
class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, PathEndpointMixin):
|
||||
_name: str
|
||||
speed: BigInt | None
|
||||
wwn: str | None
|
||||
parent: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
bridge: Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')] | None
|
||||
|
||||
15
netbox/dcim/migrations/0227_alter_interface_speed_bigint.py
Normal file
15
netbox/dcim/migrations/0227_alter_interface_speed_bigint.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('dcim', '0226_modulebay_rebuild_tree'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='interface',
|
||||
name='speed',
|
||||
field=models.PositiveBigIntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -806,7 +806,7 @@ class Interface(
|
||||
verbose_name=_('management only'),
|
||||
help_text=_('This interface is used only for out-of-band management')
|
||||
)
|
||||
speed = models.PositiveIntegerField(
|
||||
speed = models.PositiveBigIntegerField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('speed (Kbps)')
|
||||
|
||||
@@ -1930,9 +1930,9 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
|
||||
{
|
||||
'device': device.pk,
|
||||
'name': 'Interface 4',
|
||||
'type': '1000base-t',
|
||||
'type': 'other',
|
||||
'mode': InterfaceModeChoices.MODE_TAGGED,
|
||||
'speed': 1000000,
|
||||
'speed': 16_000_000_000,
|
||||
'duplex': 'full',
|
||||
'vrf': vrfs[0].pk,
|
||||
'poe_mode': InterfacePoEModeChoices.MODE_PD,
|
||||
|
||||
@@ -4655,7 +4655,7 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
enabled=True,
|
||||
mgmt_only=True,
|
||||
tx_power=40,
|
||||
speed=100000,
|
||||
speed=16_000_000_000,
|
||||
duplex='full',
|
||||
poe_mode=InterfacePoEModeChoices.MODE_PD,
|
||||
poe_type=InterfacePoETypeChoices.TYPE_2_8023AT,
|
||||
@@ -4757,7 +4757,7 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_speed(self):
|
||||
params = {'speed': [1000000, 100000]}
|
||||
params = {'speed': [16_000_000_000, 1_000_000, 100_000]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
|
||||
|
||||
def test_duplex(self):
|
||||
|
||||
@@ -2961,13 +2961,13 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
||||
cls.form_data = {
|
||||
'device': device.pk,
|
||||
'name': 'Interface X',
|
||||
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
|
||||
'type': InterfaceTypeChoices.TYPE_OTHER,
|
||||
'enabled': False,
|
||||
'bridge': interfaces[4].pk,
|
||||
'lag': interfaces[3].pk,
|
||||
'wwn': EUI('01:02:03:04:05:06:07:08', version=64),
|
||||
'mtu': 65000,
|
||||
'speed': 1000000,
|
||||
'speed': 16_000_000_000,
|
||||
'duplex': 'full',
|
||||
'mgmt_only': True,
|
||||
'description': 'A front port',
|
||||
@@ -2985,13 +2985,13 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
||||
cls.bulk_create_data = {
|
||||
'device': device.pk,
|
||||
'name': 'Interface [4-6]',
|
||||
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
|
||||
'type': InterfaceTypeChoices.TYPE_OTHER,
|
||||
'enabled': False,
|
||||
'bridge': interfaces[4].pk,
|
||||
'lag': interfaces[3].pk,
|
||||
'wwn': EUI('01:02:03:04:05:06:07:08', version=64),
|
||||
'mtu': 2000,
|
||||
'speed': 100000,
|
||||
'speed': 16_000_000_000,
|
||||
'duplex': 'half',
|
||||
'mgmt_only': True,
|
||||
'description': 'A front port',
|
||||
|
||||
@@ -7,9 +7,12 @@ from django_filters.constants import EMPTY_VALUES
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import extend_schema_field
|
||||
|
||||
from .forms.fields import BigIntegerField
|
||||
|
||||
__all__ = (
|
||||
'ContentTypeFilter',
|
||||
'MultiValueArrayFilter',
|
||||
'MultiValueBigNumberFilter',
|
||||
'MultiValueCharFilter',
|
||||
'MultiValueContentTypeFilter',
|
||||
'MultiValueDateFilter',
|
||||
@@ -77,6 +80,11 @@ class MultiValueNumberFilter(django_filters.MultipleChoiceFilter):
|
||||
field_class = multivalue_field_factory(forms.IntegerField)
|
||||
|
||||
|
||||
@extend_schema_field(OpenApiTypes.INT64)
|
||||
class MultiValueBigNumberFilter(MultiValueNumberFilter):
|
||||
field_class = multivalue_field_factory(BigIntegerField)
|
||||
|
||||
|
||||
@extend_schema_field(OpenApiTypes.DECIMAL)
|
||||
class MultiValueDecimalFilter(django_filters.MultipleChoiceFilter):
|
||||
field_class = multivalue_field_factory(forms.DecimalField)
|
||||
|
||||
@@ -2,6 +2,7 @@ import json
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.db.models import BigIntegerField as BigIntegerModelField
|
||||
from django.db.models import Count
|
||||
from django.forms.fields import InvalidJSONInput
|
||||
from django.forms.fields import JSONField as _JSONField
|
||||
@@ -13,17 +14,39 @@ from utilities.forms import widgets
|
||||
from utilities.validators import EnhancedURLValidator
|
||||
|
||||
__all__ = (
|
||||
'BigIntegerField',
|
||||
'ColorField',
|
||||
'CommentField',
|
||||
'JSONField',
|
||||
'LaxURLField',
|
||||
'MACAddressField',
|
||||
'PositiveBigIntegerField',
|
||||
'QueryField',
|
||||
'SlugField',
|
||||
'TagFilterField',
|
||||
)
|
||||
|
||||
|
||||
class BigIntegerField(forms.IntegerField):
|
||||
"""
|
||||
An IntegerField constrained to the range of a signed 64-bit integer.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('min_value', -BigIntegerModelField.MAX_BIGINT - 1)
|
||||
kwargs.setdefault('max_value', BigIntegerModelField.MAX_BIGINT)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class PositiveBigIntegerField(BigIntegerField):
|
||||
"""
|
||||
An IntegerField constrained to the range supported by Django's
|
||||
PositiveBigIntegerField model field.
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('min_value', 0)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class QueryField(forms.CharField):
|
||||
"""
|
||||
A CharField subclass used for global search/query fields in filter forms.
|
||||
|
||||
Reference in New Issue
Block a user