mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-30 04:16:24 -06:00
Misc cleanup; add tests for Q-in-Q fields
This commit is contained in:
parent
f15c26eac6
commit
cf72b7cb63
@ -33,4 +33,4 @@ For VLANs which comprise a Q-in-Q/IEEE 802.1ad topology, this field indicates wh
|
||||
|
||||
### Q-in-Q Service VLAN
|
||||
|
||||
The designated parent service VLAN for a Q-in-Q customer VLAN.
|
||||
The designated parent service VLAN for a Q-in-Q customer VLAN. This may be set only for Q-in-Q custom VLANs.
|
||||
|
@ -385,6 +385,7 @@ class InterfaceType(IPAddressesMixin, ModularComponentType, CabledObjectMixin, P
|
||||
wireless_link: Annotated["WirelessLinkType", strawberry.lazy('wireless.graphql.types')] | None
|
||||
untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
qinq_svlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
|
||||
vdcs: List[Annotated["VirtualDeviceContextType", strawberry.lazy('dcim.graphql.types')]]
|
||||
tagged_vlans: List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]
|
||||
|
@ -576,7 +576,7 @@ class BaseInterface(models.Model):
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
# Virtual Interfaces cannot have a Cable attached
|
||||
# SVLAN can be defined only for Q-in-Q interfaces
|
||||
if self.qinq_svlan and self.mode != InterfaceModeChoices.MODE_Q_IN_Q:
|
||||
raise ValidationError({
|
||||
'qinq_svlan': _("Only Q-in-Q interfaces may specify a service VLAN.")
|
||||
|
@ -7,6 +7,7 @@ from dcim.choices import *
|
||||
from dcim.constants import *
|
||||
from dcim.models import *
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import ASN, RIR, VLAN, VRF
|
||||
from netbox.api.serializers import GenericObjectSerializer
|
||||
from tenancy.models import Tenant
|
||||
@ -1618,6 +1619,7 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
|
||||
VLAN(name='VLAN 1', vid=1),
|
||||
VLAN(name='VLAN 2', vid=2),
|
||||
VLAN(name='VLAN 3', vid=3),
|
||||
VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
@ -1676,18 +1678,22 @@ class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase
|
||||
'vdcs': [vdcs[1].pk],
|
||||
'name': 'Interface 7',
|
||||
'type': InterfaceTypeChoices.TYPE_80211A,
|
||||
'mode': InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
'tx_power': 10,
|
||||
'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk],
|
||||
'rf_channel': WirelessChannelChoices.CHANNEL_5G_32,
|
||||
'qinq_svlan': vlans[3].pk,
|
||||
},
|
||||
{
|
||||
'device': device.pk,
|
||||
'vdcs': [vdcs[1].pk],
|
||||
'name': 'Interface 8',
|
||||
'type': InterfaceTypeChoices.TYPE_80211A,
|
||||
'mode': InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
'tx_power': 10,
|
||||
'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk],
|
||||
'rf_channel': "",
|
||||
'qinq_svlan': vlans[3].pk,
|
||||
},
|
||||
]
|
||||
|
||||
|
@ -4,7 +4,8 @@ from circuits.models import Circuit, CircuitTermination, CircuitType, Provider
|
||||
from dcim.choices import *
|
||||
from dcim.filtersets import *
|
||||
from dcim.models import *
|
||||
from ipam.models import ASN, IPAddress, RIR, VRF
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import ASN, IPAddress, RIR, VLAN, VRF
|
||||
from netbox.choices import ColorChoices, WeightUnitChoices
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from users.models import User
|
||||
@ -3520,7 +3521,7 @@ class PowerOutletTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedF
|
||||
class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilterSetTests):
|
||||
queryset = Interface.objects.all()
|
||||
filterset = InterfaceFilterSet
|
||||
ignore_fields = ('tagged_vlans', 'untagged_vlan', 'vdcs')
|
||||
ignore_fields = ('tagged_vlans', 'untagged_vlan', 'qinq_svlan', 'vdcs')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@ -3669,6 +3670,13 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
)
|
||||
VirtualDeviceContext.objects.bulk_create(vdcs)
|
||||
|
||||
vlans = (
|
||||
VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(name='SVLAN 2', vid=1002, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(name='SVLAN 3', vid=1003, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
interfaces = (
|
||||
Interface(
|
||||
device=devices[0],
|
||||
@ -3742,7 +3750,9 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
speed=100000,
|
||||
duplex='full',
|
||||
poe_mode=InterfacePoEModeChoices.MODE_PD,
|
||||
poe_type=InterfacePoETypeChoices.TYPE_2_8023AT
|
||||
poe_type=InterfacePoETypeChoices.TYPE_2_8023AT,
|
||||
mode=InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
qinq_svlan=vlans[0]
|
||||
),
|
||||
Interface(
|
||||
device=devices[4],
|
||||
@ -3751,7 +3761,9 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
type=InterfaceTypeChoices.TYPE_OTHER,
|
||||
enabled=True,
|
||||
mgmt_only=True,
|
||||
tx_power=40
|
||||
tx_power=40,
|
||||
mode=InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
qinq_svlan=vlans[1]
|
||||
),
|
||||
Interface(
|
||||
device=devices[4],
|
||||
@ -3760,7 +3772,9 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
type=InterfaceTypeChoices.TYPE_OTHER,
|
||||
enabled=False,
|
||||
mgmt_only=False,
|
||||
tx_power=40
|
||||
tx_power=40,
|
||||
mode=InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
qinq_svlan=vlans[2]
|
||||
),
|
||||
Interface(
|
||||
device=devices[4],
|
||||
@ -4016,6 +4030,13 @@ class InterfaceTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFil
|
||||
params = {'vdc_identifier': vdc.values_list('identifier', flat=True)}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
|
||||
|
||||
def test_vlan(self):
|
||||
vlan = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE).first()
|
||||
params = {'vlan_id': vlan.pk}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||
params = {'vlan': vlan.vid}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||
|
||||
|
||||
class FrontPortTestCase(TestCase, DeviceComponentFilterSetTests, ChangeLoggedFilterSetTests):
|
||||
queryset = FrontPort.objects.all()
|
||||
|
@ -64,7 +64,7 @@ class VLANSerializer(NetBoxModelSerializer):
|
||||
status = ChoiceField(choices=VLANStatusChoices, required=False)
|
||||
role = RoleSerializer(nested=True, required=False, allow_null=True)
|
||||
qinq_role = ChoiceField(choices=VLANQinQRoleChoices, required=False)
|
||||
qinq_svlan = NestedVLANSerializer(required=False, allow_null=True)
|
||||
qinq_svlan = NestedVLANSerializer(required=False, allow_null=True, default=None)
|
||||
l2vpn_termination = L2VPNTerminationSerializer(nested=True, read_only=True, allow_null=True)
|
||||
|
||||
# Related object counts
|
||||
|
@ -1040,14 +1040,13 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
|
||||
method='get_for_virtualmachine'
|
||||
)
|
||||
qinq_role = django_filters.MultipleChoiceFilter(
|
||||
choices=VLANQinQRoleChoices,
|
||||
null_value=None
|
||||
choices=VLANQinQRoleChoices
|
||||
)
|
||||
qinq_svlan_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=VLAN.objects.all(),
|
||||
label=_('Q-in-Q SVLAN (ID)'),
|
||||
)
|
||||
qinq_svlan_vid = django_filters.NumberFilter(
|
||||
qinq_svlan_vid = MultiValueNumberFilter(
|
||||
field_name='qinq_svlan__vid',
|
||||
label=_('Q-in-Q SVLAN number (1-4094)'),
|
||||
)
|
||||
|
@ -526,10 +526,18 @@ class VLANBulkEditForm(NetBoxModelBulkEditForm):
|
||||
required=False
|
||||
)
|
||||
qinq_role = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
label=_('Q-in-Q role'),
|
||||
choices=add_blank_choice(VLANQinQRoleChoices),
|
||||
required=False
|
||||
)
|
||||
qinq_svlan = DynamicModelChoiceField(
|
||||
label=_('Q-in-Q SVLAN'),
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
query_params={
|
||||
'qinq_role': VLANQinQRoleChoices.ROLE_SERVICE,
|
||||
}
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = VLAN
|
||||
|
@ -440,11 +440,6 @@ class VLANImportForm(NetBoxModelImportForm):
|
||||
to_field_name='name',
|
||||
help_text=_('Assigned VLAN group')
|
||||
)
|
||||
qinq_role = CSVChoiceField(
|
||||
label=_('Q-in-Q role'),
|
||||
choices=VLANStatusChoices,
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
tenant = CSVModelChoiceField(
|
||||
label=_('Tenant'),
|
||||
queryset=Tenant.objects.all(),
|
||||
@ -464,6 +459,12 @@ class VLANImportForm(NetBoxModelImportForm):
|
||||
to_field_name='name',
|
||||
help_text=_('Functional role')
|
||||
)
|
||||
qinq_role = CSVChoiceField(
|
||||
label=_('Q-in-Q role'),
|
||||
choices=VLANStatusChoices,
|
||||
required=False,
|
||||
help_text=_('Operational status')
|
||||
)
|
||||
qinq_svlan = CSVModelChoiceField(
|
||||
label=_('Q-in-Q SVLAN'),
|
||||
queryset=VLAN.objects.all(),
|
||||
|
@ -467,7 +467,7 @@ class VLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
FieldSet('q', 'filter_id', 'tag'),
|
||||
FieldSet('region_id', 'site_group_id', 'site_id', name=_('Location')),
|
||||
FieldSet('group_id', 'status', 'role_id', 'vid', 'l2vpn_id', name=_('Attributes')),
|
||||
FieldSet('qinq_role', 'qinq_svlan', name=_('Q-in-Q/802.1ad')),
|
||||
FieldSet('qinq_role', 'qinq_svlan_id', name=_('Q-in-Q/802.1ad')),
|
||||
FieldSet('tenant_group_id', 'tenant_id', name=_('Tenant')),
|
||||
)
|
||||
selector_fields = ('filter_id', 'q', 'site_id')
|
||||
|
@ -234,7 +234,7 @@ class ServiceTemplateType(NetBoxObjectType):
|
||||
|
||||
@strawberry_django.type(
|
||||
models.VLAN,
|
||||
fields='__all__',
|
||||
exclude=('qinq_svlan',),
|
||||
filters=VLANFilter
|
||||
)
|
||||
class VLANType(NetBoxObjectType):
|
||||
@ -250,6 +250,10 @@ class VLANType(NetBoxObjectType):
|
||||
interfaces_as_tagged: List[Annotated["InterfaceType", strawberry.lazy('dcim.graphql.types')]]
|
||||
vminterfaces_as_tagged: List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]]
|
||||
|
||||
@strawberry_django.field
|
||||
def qinq_svlan(self) -> Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None:
|
||||
return self.qinq_svlan
|
||||
|
||||
|
||||
@strawberry_django.type(
|
||||
models.VLANGroup,
|
||||
|
@ -980,6 +980,7 @@ class VLANTest(APIViewTestCases.APIViewTestCase):
|
||||
VLAN(name='VLAN 1', vid=1, group=vlan_groups[0]),
|
||||
VLAN(name='VLAN 2', vid=2, group=vlan_groups[0]),
|
||||
VLAN(name='VLAN 3', vid=3, group=vlan_groups[0]),
|
||||
VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
@ -999,6 +1000,12 @@ class VLANTest(APIViewTestCases.APIViewTestCase):
|
||||
'name': 'VLAN 6',
|
||||
'group': vlan_groups[1].pk,
|
||||
},
|
||||
{
|
||||
'vid': 2001,
|
||||
'name': 'CVLAN 1',
|
||||
'qinq_role': VLANQinQRoleChoices.ROLE_CUSTOMER,
|
||||
'qinq_svlan': vlans[3].pk,
|
||||
},
|
||||
]
|
||||
|
||||
def test_delete_vlan_with_prefix(self):
|
||||
|
@ -1630,6 +1630,7 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
Site(name='Site 4', slug='site-4', region=regions[0], group=site_groups[0]),
|
||||
Site(name='Site 5', slug='site-5', region=regions[1], group=site_groups[1]),
|
||||
Site(name='Site 6', slug='site-6', region=regions[2], group=site_groups[2]),
|
||||
Site(name='Site 7', slug='site-7'),
|
||||
)
|
||||
Site.objects.bulk_create(sites)
|
||||
|
||||
@ -1784,9 +1785,21 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
|
||||
# Create one globally available VLAN
|
||||
VLAN(vid=1000, name='Global VLAN'),
|
||||
|
||||
# Create some Q-in-Q service VLANs
|
||||
VLAN(vid=2001, name='SVLAN 1', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(vid=2002, name='SVLAN 2', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(vid=2003, name='SVLAN 3', site=sites[6], qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
# Create Q-in-Q customer VLANs
|
||||
VLAN.objects.bulk_create([
|
||||
VLAN(vid=3001, name='CVLAN 1', site=sites[6], qinq_svlan=vlans[29], qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER),
|
||||
VLAN(vid=3002, name='CVLAN 2', site=sites[6], qinq_svlan=vlans[30], qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER),
|
||||
VLAN(vid=3003, name='CVLAN 3', site=sites[6], qinq_svlan=vlans[31], qinq_role=VLANQinQRoleChoices.ROLE_CUSTOMER),
|
||||
])
|
||||
|
||||
# Assign VLANs to device interfaces
|
||||
interfaces[0].untagged_vlan = vlans[0]
|
||||
interfaces[0].tagged_vlans.add(vlans[1])
|
||||
@ -1897,6 +1910,17 @@ class VLANTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
params = {'vminterface_id': vminterface_id}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||
|
||||
def test_qinq_role(self):
|
||||
params = {'qinq_role': [VLANQinQRoleChoices.ROLE_SERVICE, VLANQinQRoleChoices.ROLE_CUSTOMER]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
|
||||
|
||||
def test_qinq_svlan(self):
|
||||
vlans = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE)[:2]
|
||||
params = {'qinq_svlan_id': [vlans[0].pk, vlans[1].pk]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
params = {'qinq_svlan_vid': [vlans[0].vid, vlans[1].vid]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
||||
class ServiceTemplateTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
queryset = ServiceTemplate.objects.all()
|
||||
|
@ -64,7 +64,13 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Q-in-Q Role" %}</th>
|
||||
<td>{% badge object.get_qinq_role_display bg_color=object.get_qinq_role_color %}</td>
|
||||
<td>
|
||||
{% if object.qinq_role %}
|
||||
{% badge object.get_qinq_role_display bg_color=object.get_qinq_role_color %}
|
||||
{% else %}
|
||||
{{ ''|placeholder }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if object.qinq_role == 'c-vlan' %}
|
||||
<tr>
|
||||
|
@ -100,6 +100,7 @@ class VMInterfaceType(IPAddressesMixin, ComponentType):
|
||||
bridge: Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')] | None
|
||||
untagged_vlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
vrf: Annotated["VRFType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
qinq_svlan: Annotated["VLANType", strawberry.lazy('ipam.graphql.types')] | None
|
||||
|
||||
tagged_vlans: List[Annotated["VLANType", strawberry.lazy('ipam.graphql.types')]]
|
||||
bridge_interfaces: List[Annotated["VMInterfaceType", strawberry.lazy('virtualization.graphql.types')]]
|
||||
|
@ -4,6 +4,7 @@ from rest_framework import status
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.models import Site
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import VLAN, VRF
|
||||
from utilities.testing import APITestCase, APIViewTestCases, create_test_device, create_test_virtualmachine
|
||||
from virtualization.choices import *
|
||||
@ -270,6 +271,7 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
|
||||
VLAN(name='VLAN 1', vid=1),
|
||||
VLAN(name='VLAN 2', vid=2),
|
||||
VLAN(name='VLAN 3', vid=3),
|
||||
VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
@ -307,6 +309,12 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
|
||||
'untagged_vlan': vlans[2].pk,
|
||||
'vrf': vrfs[2].pk,
|
||||
},
|
||||
{
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Interface 7',
|
||||
'mode': InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
'qinq_svlan': vlans[3].pk,
|
||||
},
|
||||
]
|
||||
|
||||
def test_bulk_delete_child_interfaces(self):
|
||||
|
@ -1,7 +1,9 @@
|
||||
from django.test import TestCase
|
||||
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.models import Device, DeviceRole, Platform, Region, Site, SiteGroup
|
||||
from ipam.models import IPAddress, VRF
|
||||
from ipam.choices import VLANQinQRoleChoices
|
||||
from ipam.models import IPAddress, VLAN, VRF
|
||||
from tenancy.models import Tenant, TenantGroup
|
||||
from utilities.testing import ChangeLoggedFilterSetTests, create_test_device
|
||||
from virtualization.choices import *
|
||||
@ -528,7 +530,7 @@ class VirtualMachineTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
queryset = VMInterface.objects.all()
|
||||
filterset = VMInterfaceFilterSet
|
||||
ignore_fields = ('tagged_vlans', 'untagged_vlan',)
|
||||
ignore_fields = ('tagged_vlans', 'untagged_vlan', 'qinq_svlan')
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@ -554,6 +556,13 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
)
|
||||
VRF.objects.bulk_create(vrfs)
|
||||
|
||||
vlans = (
|
||||
VLAN(name='SVLAN 1', vid=1001, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(name='SVLAN 2', vid=1002, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
VLAN(name='SVLAN 3', vid=1003, qinq_role=VLANQinQRoleChoices.ROLE_SERVICE),
|
||||
)
|
||||
VLAN.objects.bulk_create(vlans)
|
||||
|
||||
vms = (
|
||||
VirtualMachine(name='Virtual Machine 1', cluster=clusters[0]),
|
||||
VirtualMachine(name='Virtual Machine 2', cluster=clusters[1]),
|
||||
@ -587,7 +596,9 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
mtu=300,
|
||||
mac_address='00-00-00-00-00-03',
|
||||
vrf=vrfs[2],
|
||||
description='foobar3'
|
||||
description='foobar3',
|
||||
mode=InterfaceModeChoices.MODE_Q_IN_Q,
|
||||
qinq_svlan=vlans[0]
|
||||
),
|
||||
)
|
||||
VMInterface.objects.bulk_create(interfaces)
|
||||
@ -658,6 +669,13 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
params = {'description': ['foobar1', 'foobar2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_vlan(self):
|
||||
vlan = VLAN.objects.filter(qinq_role=VLANQinQRoleChoices.ROLE_SERVICE).first()
|
||||
params = {'vlan_id': vlan.pk}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||
params = {'vlan': vlan.vid}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||
|
||||
|
||||
class VirtualDiskTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
queryset = VirtualDisk.objects.all()
|
||||
|
Loading…
Reference in New Issue
Block a user