From 53372a747109479f632fc916244d14fb75253f60 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Mon, 11 Jul 2022 21:51:39 -0400 Subject: [PATCH] #8157: General cleanup & fix tests --- netbox/ipam/filtersets.py | 25 ++-- netbox/ipam/forms/bulk_edit.py | 9 +- netbox/ipam/forms/bulk_import.py | 2 +- netbox/ipam/forms/filtersets.py | 38 ++++-- netbox/ipam/forms/models.py | 6 +- netbox/ipam/migrations/0059_l2vpn.py | 6 +- netbox/ipam/models/ip.py | 2 +- netbox/ipam/models/l2vpn.py | 11 +- netbox/ipam/tables/l2vpn.py | 11 +- netbox/ipam/tests/test_api.py | 2 - netbox/ipam/tests/test_filtersets.py | 126 ++++++++++++------ netbox/ipam/tests/test_views.py | 37 ++--- netbox/templates/ipam/l2vpn.html | 98 +++++++------- .../templates/ipam/l2vpntermination_edit.html | 4 +- 14 files changed, 213 insertions(+), 164 deletions(-) diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index f682009ee..edd1867ed 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -930,8 +930,11 @@ class ServiceFilterSet(NetBoxModelFilterSet): # L2VPN # - class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet): + type = django_filters.MultipleChoiceFilter( + choices=L2VPNTypeChoices, + null_value=None + ) import_target_id = django_filters.ModelMultipleChoiceFilter( field_name='import_targets', queryset=RouteTarget.objects.all(), @@ -972,10 +975,10 @@ class L2VPNTerminationFilterSet(NetBoxModelFilterSet): label='L2VPN (ID)', ) l2vpn = django_filters.ModelMultipleChoiceFilter( - field_name='l2vpn__name', + field_name='l2vpn__slug', queryset=L2VPN.objects.all(), - to_field_name='name', - label='L2VPN (name)', + to_field_name='slug', + label='L2VPN (slug)', ) device = MultiValueCharFilter( method='filter_device', @@ -987,17 +990,16 @@ class L2VPNTerminationFilterSet(NetBoxModelFilterSet): field_name='pk', label='Device (ID)', ) - interface = django_filters.ModelMultipleChoiceFilter( - field_name='interface__name', - queryset=Interface.objects.all(), - to_field_name='name', - label='Interface (name)', - ) interface_id = django_filters.ModelMultipleChoiceFilter( field_name='interface', queryset=Interface.objects.all(), label='Interface (ID)', ) + vminterface_id = django_filters.ModelMultipleChoiceFilter( + field_name='vminterface', + queryset=VMInterface.objects.all(), + label='VM Interface (ID)', + ) vlan = django_filters.ModelMultipleChoiceFilter( field_name='vlan__name', queryset=VLAN.objects.all(), @@ -1013,10 +1015,11 @@ class L2VPNTerminationFilterSet(NetBoxModelFilterSet): queryset=VLAN.objects.all(), label='VLAN (ID)', ) + assigned_object_type = ContentTypeFilter() class Meta: model = L2VPNTermination - fields = ['id', ] + fields = ('id', 'assigned_object_type_id') def search(self, queryset, name, value): if not value.strip(): diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py index 50fc51522..5f579b07f 100644 --- a/netbox/ipam/forms/bulk_edit.py +++ b/netbox/ipam/forms/bulk_edit.py @@ -8,7 +8,7 @@ from ipam.models import ASN from netbox.forms import NetBoxModelBulkEditForm from tenancy.models import Tenant from utilities.forms import ( - add_blank_choice, BulkEditNullBooleanSelect, DatePicker, DynamicModelChoiceField, NumericArrayField, StaticSelect, + add_blank_choice, BulkEditNullBooleanSelect, DynamicModelChoiceField, NumericArrayField, StaticSelect, DynamicModelMultipleChoiceField, ) @@ -445,6 +445,11 @@ class ServiceBulkEditForm(ServiceTemplateBulkEditForm): class L2VPNBulkEditForm(NetBoxModelBulkEditForm): + type = forms.ChoiceField( + choices=add_blank_choice(L2VPNTypeChoices), + required=False, + widget=StaticSelect() + ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False @@ -456,7 +461,7 @@ class L2VPNBulkEditForm(NetBoxModelBulkEditForm): model = L2VPN fieldsets = ( - (None, ('tenant', 'description')), + (None, ('type', 'description', 'tenant')), ) nullable_fields = ('tenant', 'description',) diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py index b8dd1c54c..880d2722f 100644 --- a/netbox/ipam/forms/bulk_import.py +++ b/netbox/ipam/forms/bulk_import.py @@ -438,7 +438,7 @@ class L2VPNCSVForm(NetBoxModelCSVForm): ) type = CSVChoiceField( choices=L2VPNTypeChoices, - help_text='IP protocol' + help_text='L2VPN type' ) class Meta: diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py index 795cfe378..384a4da33 100644 --- a/netbox/ipam/forms/filtersets.py +++ b/netbox/ipam/forms/filtersets.py @@ -1,18 +1,19 @@ from django import forms +from django.contrib.contenttypes.models import ContentType +from django.db.models import Q from django.utils.translation import gettext as _ from dcim.models import Location, Rack, Region, Site, SiteGroup, Device -from virtualization.models import VirtualMachine from ipam.choices import * from ipam.constants import * from ipam.models import * -from ipam.models import ASN from netbox.forms import NetBoxModelFilterSetForm from tenancy.forms import TenancyFilterForm from utilities.forms import ( - add_blank_choice, DynamicModelChoiceField, DynamicModelMultipleChoiceField, MultipleChoiceField, StaticSelect, - TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, + add_blank_choice, ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, + MultipleChoiceField, StaticSelect, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES, ) +from virtualization.models import VirtualMachine __all__ = ( 'AggregateFilterForm', @@ -482,7 +483,8 @@ class ServiceFilterForm(ServiceTemplateFilterForm): class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): model = L2VPN fieldsets = ( - (None, ('type', )), + (None, ('q', 'tag')), + ('Attributes', ('type', 'import_target_id', 'export_target_id')), ('Tenant', ('tenant_group_id', 'tenant_id')), ) type = forms.ChoiceField( @@ -490,17 +492,31 @@ class L2VPNFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm): required=False, widget=StaticSelect() ) + import_target_id = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + required=False, + label=_('Import targets') + ) + export_target_id = DynamicModelMultipleChoiceField( + queryset=RouteTarget.objects.all(), + required=False, + label=_('Export targets') + ) + tag = TagFilterField(model) class L2VPNTerminationFilterForm(NetBoxModelFilterSetForm): model = L2VPNTermination fieldsets = ( - (None, ('l2vpn', )), + (None, ('l2vpn_id', 'assigned_object_type_id')), ) - l2vpn = DynamicModelChoiceField( + l2vpn_id = DynamicModelChoiceField( queryset=L2VPN.objects.all(), - required=True, - query_params={}, - label='L2VPN', - fetch_trigger='open' + required=False, + label='L2VPN' + ) + assigned_object_type_id = ContentTypeMultipleChoiceField( + queryset=ContentType.objects.all(), + required=False, + label='Object type' ) diff --git a/netbox/ipam/forms/models.py b/netbox/ipam/forms/models.py index 3986eee32..415c952be 100644 --- a/netbox/ipam/forms/models.py +++ b/netbox/ipam/forms/models.py @@ -916,7 +916,8 @@ class L2VPNTerminationForm(NetBoxModelForm): required=False, query_params={ 'available_on_device': '$device' - } + }, + label='VLAN' ) interface = DynamicModelChoiceField( queryset=Interface.objects.all(), @@ -935,7 +936,8 @@ class L2VPNTerminationForm(NetBoxModelForm): required=False, query_params={ 'virtual_machine_id': '$virtual_machine' - } + }, + label='Interface' ) class Meta: diff --git a/netbox/ipam/migrations/0059_l2vpn.py b/netbox/ipam/migrations/0059_l2vpn.py index ef670ddea..7436989f7 100644 --- a/netbox/ipam/migrations/0059_l2vpn.py +++ b/netbox/ipam/migrations/0059_l2vpn.py @@ -27,7 +27,7 @@ class Migration(migrations.Migration): ('slug', models.SlugField()), ('type', models.CharField(max_length=50)), ('identifier', models.BigIntegerField(blank=True, null=True, unique=True)), - ('description', models.TextField(blank=True, null=True)), + ('description', models.CharField(blank=True, max_length=200)), ('export_targets', models.ManyToManyField(blank=True, related_name='exporting_l2vpns', to='ipam.routetarget')), ('import_targets', models.ManyToManyField(blank=True, related_name='importing_l2vpns', to='ipam.routetarget')), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), @@ -35,7 +35,7 @@ class Migration(migrations.Migration): ], options={ 'verbose_name': 'L2VPN', - 'ordering': ('identifier', 'name'), + 'ordering': ('name', 'identifier'), }, ), migrations.CreateModel( @@ -51,7 +51,7 @@ class Migration(migrations.Migration): ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ], options={ - 'verbose_name': 'L2VPN Termination', + 'verbose_name': 'L2VPN termination', 'ordering': ('l2vpn',), }, ), diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py index 0bc0e2364..ee5de8cf4 100644 --- a/netbox/ipam/models/ip.py +++ b/netbox/ipam/models/ip.py @@ -931,7 +931,7 @@ class IPAddress(NetBoxModel): # Populate the address field with the next available IP (if any) if next_available_ip := self.get_next_available_ip(): - attrs['address'] = next_available_ip + attrs['address'] = f'{next_available_ip}/{self.address.prefixlen}' return attrs diff --git a/netbox/ipam/models/l2vpn.py b/netbox/ipam/models/l2vpn.py index dd8c51984..5d85fe915 100644 --- a/netbox/ipam/models/l2vpn.py +++ b/netbox/ipam/models/l2vpn.py @@ -31,7 +31,10 @@ class L2VPN(NetBoxModel): related_name='exporting_l2vpns', blank=True ) - description = models.TextField(null=True, blank=True) + description = models.CharField( + max_length=200, + blank=True + ) tenant = models.ForeignKey( to='tenancy.Tenant', on_delete=models.PROTECT, @@ -44,7 +47,7 @@ class L2VPN(NetBoxModel): ) class Meta: - ordering = ('identifier', 'name') + ordering = ('name', 'identifier') verbose_name = 'L2VPN' def __str__(self): @@ -76,7 +79,7 @@ class L2VPNTermination(NetBoxModel): class Meta: ordering = ('l2vpn',) - verbose_name = 'L2VPN Termination' + verbose_name = 'L2VPN termination' constraints = ( models.UniqueConstraint( fields=('assigned_object_type', 'assigned_object_id'), @@ -102,7 +105,7 @@ class L2VPNTermination(NetBoxModel): raise ValidationError(f'L2VPN Termination already assigned ({self.assigned_object})') # Only check if L2VPN is set and is of type P2P - if self.l2vpn and self.l2vpn.type in L2VPNTypeChoices.P2P: + if hasattr(self, 'l2vpn') and self.l2vpn.type in L2VPNTypeChoices.P2P: terminations_count = L2VPNTermination.objects.filter(l2vpn=self.l2vpn).exclude(pk=self.pk).count() if terminations_count >= 2: l2vpn_type = self.l2vpn.get_type_display() diff --git a/netbox/ipam/tables/l2vpn.py b/netbox/ipam/tables/l2vpn.py index a0e2f5d67..5be525343 100644 --- a/netbox/ipam/tables/l2vpn.py +++ b/netbox/ipam/tables/l2vpn.py @@ -1,8 +1,8 @@ import django_tables2 as tables -from ipam.models import * -from ipam.models.l2vpn import L2VPN, L2VPNTermination +from ipam.models import L2VPN, L2VPNTermination from netbox.tables import NetBoxTable, columns +from tenancy.tables import TenancyColumnsMixin __all__ = ( 'L2VPNTable', @@ -16,7 +16,7 @@ L2VPN_TARGETS = """ """ -class L2VPNTable(NetBoxTable): +class L2VPNTable(TenancyColumnsMixin, NetBoxTable): pk = columns.ToggleColumn() name = tables.Column( linkify=True @@ -32,7 +32,10 @@ class L2VPNTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = L2VPN - fields = ('pk', 'name', 'slug', 'type', 'description', 'import_targets', 'export_targets', 'tenant', 'actions') + fields = ( + 'pk', 'name', 'slug', 'type', 'description', 'import_targets', 'export_targets', 'tenant', 'tenant_group', + 'actions', + ) default_columns = ('pk', 'name', 'type', 'description', 'actions') diff --git a/netbox/ipam/tests/test_api.py b/netbox/ipam/tests/test_api.py index a5ebef2c7..3fef04194 100644 --- a/netbox/ipam/tests/test_api.py +++ b/netbox/ipam/tests/test_api.py @@ -970,7 +970,6 @@ class L2VPNTerminationTest(APIViewTestCases.APIViewTestCase): VLAN(name='VLAN 6', vid=656), VLAN(name='VLAN 7', vid=657) ) - VLAN.objects.bulk_create(vlans) l2vpns = ( @@ -985,7 +984,6 @@ class L2VPNTerminationTest(APIViewTestCases.APIViewTestCase): L2VPNTermination(l2vpn=l2vpns[0], assigned_object=vlans[1]), L2VPNTermination(l2vpn=l2vpns[0], assigned_object=vlans[2]) ) - L2VPNTermination.objects.bulk_create(l2vpnterminations) cls.create_data = [ diff --git a/netbox/ipam/tests/test_filtersets.py b/netbox/ipam/tests/test_filtersets.py index 2b5fb0759..9106a4965 100644 --- a/netbox/ipam/tests/test_filtersets.py +++ b/netbox/ipam/tests/test_filtersets.py @@ -1,6 +1,8 @@ +from django.contrib.contenttypes.models import ContentType from django.test import TestCase from netaddr import IPNetwork +from dcim.choices import InterfaceTypeChoices from dcim.models import Device, DeviceRole, DeviceType, Interface, Location, Manufacturer, Rack, Region, Site, SiteGroup from ipam.choices import * from ipam.filtersets import * @@ -1472,12 +1474,54 @@ class L2VPNTestCase(TestCase, ChangeLoggedFilterSetTests): @classmethod def setUpTestData(cls): + route_targets = ( + RouteTarget(name='1:1'), + RouteTarget(name='1:2'), + RouteTarget(name='1:3'), + RouteTarget(name='2:1'), + RouteTarget(name='2:2'), + RouteTarget(name='2:3'), + ) + RouteTarget.objects.bulk_create(route_targets) + l2vpns = ( - L2VPN(name='L2VPN 1', type='vxlan', identifier=650001), - L2VPN(name='L2VPN 2', type='vpws', identifier=650002), - L2VPN(name='L2VPN 3', type='vpls'), # No RD + L2VPN(name='L2VPN 1', type=L2VPNTypeChoices.TYPE_VXLAN, identifier=65001), + L2VPN(name='L2VPN 2', type=L2VPNTypeChoices.TYPE_VPWS, identifier=65002), + L2VPN(name='L2VPN 3', type=L2VPNTypeChoices.TYPE_VPLS), ) L2VPN.objects.bulk_create(l2vpns) + l2vpns[0].import_targets.add(route_targets[0]) + l2vpns[1].import_targets.add(route_targets[1]) + l2vpns[2].import_targets.add(route_targets[2]) + l2vpns[0].export_targets.add(route_targets[3]) + l2vpns[1].export_targets.add(route_targets[4]) + l2vpns[2].export_targets.add(route_targets[5]) + + def test_name(self): + params = {'name': ['L2VPN 1', 'L2VPN 2']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_identifier(self): + params = {'identifier': ['65001', '65002']} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_type(self): + params = {'type': [L2VPNTypeChoices.TYPE_VXLAN, L2VPNTypeChoices.TYPE_VPWS]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_import_targets(self): + route_targets = RouteTarget.objects.filter(name__in=['1:1', '1:2']) + params = {'import_target_id': [route_targets[0].pk, route_targets[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'import_target': [route_targets[0].name, route_targets[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_export_targets(self): + route_targets = RouteTarget.objects.filter(name__in=['2:1', '2:2']) + params = {'export_target_id': [route_targets[0].pk, route_targets[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'export_target': [route_targets[0].name, route_targets[1].name]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) class L2VPNTerminationTestCase(TestCase, ChangeLoggedFilterSetTests): @@ -1486,44 +1530,33 @@ class L2VPNTerminationTestCase(TestCase, ChangeLoggedFilterSetTests): @classmethod def setUpTestData(cls): - - site = Site.objects.create(name='Site 1') - manufacturer = Manufacturer.objects.create(name='Manufacturer 1') - device_type = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer) - device_role = DeviceRole.objects.create(name='Switch') - device = Device.objects.create( - name='Device 1', - site=site, - device_type=device_type, - device_role=device_role, - status='active' - ) - + device = create_test_device('Device 1') interfaces = ( - Interface(name='Interface 1', device=device, type='1000baset'), - Interface(name='Interface 2', device=device, type='1000baset'), - Interface(name='Interface 3', device=device, type='1000baset'), - Interface(name='Interface 4', device=device, type='1000baset'), - Interface(name='Interface 5', device=device, type='1000baset'), - Interface(name='Interface 6', device=device, type='1000baset') + Interface(name='Interface 1', device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(name='Interface 2', device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED), + Interface(name='Interface 3', device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED), ) - Interface.objects.bulk_create(interfaces) - vlans = ( - VLAN(name='VLAN 1', vid=651), - VLAN(name='VLAN 2', vid=652), - VLAN(name='VLAN 3', vid=653), - VLAN(name='VLAN 4', vid=654), - VLAN(name='VLAN 5', vid=655) + vm = create_test_virtualmachine('Virtual Machine 1') + vminterfaces = ( + VMInterface(name='Interface 1', virtual_machine=vm), + VMInterface(name='Interface 2', virtual_machine=vm), + VMInterface(name='Interface 3', virtual_machine=vm), ) + VMInterface.objects.bulk_create(vminterfaces) + vlans = ( + VLAN(name='VLAN 1', vid=101), + VLAN(name='VLAN 2', vid=102), + VLAN(name='VLAN 3', vid=103), + ) VLAN.objects.bulk_create(vlans) l2vpns = ( - L2VPN(name='L2VPN 1', type='vxlan', identifier=650001), - L2VPN(name='L2VPN 2', type='vpws', identifier=650002), - L2VPN(name='L2VPN 3', type='vpls'), # No RD, + L2VPN(name='L2VPN 1', slug='l2vpn-1', type='vxlan', identifier=65001), + L2VPN(name='L2VPN 2', slug='l2vpn-2', type='vpws', identifier=65002), + L2VPN(name='L2VPN 3', slug='l2vpn-3', type='vpls'), # No RD, ) L2VPN.objects.bulk_create(l2vpns) @@ -1534,27 +1567,34 @@ class L2VPNTerminationTestCase(TestCase, ChangeLoggedFilterSetTests): L2VPNTermination(l2vpn=l2vpns[0], assigned_object=interfaces[0]), L2VPNTermination(l2vpn=l2vpns[1], assigned_object=interfaces[1]), L2VPNTermination(l2vpn=l2vpns[2], assigned_object=interfaces[2]), + L2VPNTermination(l2vpn=l2vpns[0], assigned_object=vminterfaces[0]), + L2VPNTermination(l2vpn=l2vpns[1], assigned_object=vminterfaces[1]), + L2VPNTermination(l2vpn=l2vpns[2], assigned_object=vminterfaces[2]), ) - L2VPNTermination.objects.bulk_create(l2vpnterminations) - def test_l2vpns(self): + def test_l2vpn(self): l2vpns = L2VPN.objects.all()[:2] params = {'l2vpn_id': [l2vpns[0].pk, l2vpns[1].pk]} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) - params = {'l2vpn': ['L2VPN 1', 'L2VPN 2']} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) + params = {'l2vpn': [l2vpns[0].slug, l2vpns[1].slug]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) - def test_interfaces(self): + def test_content_type(self): + params = {'assigned_object_type_id': ContentType.objects.get(model='vlan').pk} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3) + + def test_interface(self): interfaces = Interface.objects.all()[:2] params = {'interface_id': [interfaces[0].pk, interfaces[1].pk]} - qs = self.filterset(params, self.queryset).qs - results = qs.all() - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - params = {'interface': ['Interface 1', 'Interface 2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - def test_vlans(self): + def test_vminterface(self): + vminterfaces = VMInterface.objects.all()[:2] + params = {'vminterface_id': [vminterfaces[0].pk, vminterfaces[1].pk]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + + def test_vlan(self): vlans = VLAN.objects.all()[:2] params = {'vlan_id': [vlans[0].pk, vlans[1].pk]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) diff --git a/netbox/ipam/tests/test_views.py b/netbox/ipam/tests/test_views.py index 890c0eae3..27520229a 100644 --- a/netbox/ipam/tests/test_views.py +++ b/netbox/ipam/tests/test_views.py @@ -1,18 +1,14 @@ import datetime -from django.contrib.contenttypes.models import ContentType from django.test import override_settings from django.urls import reverse from netaddr import IPNetwork from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site, Interface -from extras.choices import ObjectChangeActionChoices -from extras.models import ObjectChange from ipam.choices import * from ipam.models import * from tenancy.models import Tenant -from users.models import ObjectPermission -from utilities.testing import ViewTestCases, create_tags, post_data +from utilities.testing import ViewTestCases, create_test_device, create_tags class ASNTestCase(ViewTestCases.PrimaryObjectViewTestCase): @@ -772,9 +768,9 @@ class L2VPNTestCase(ViewTestCases.PrimaryObjectViewTestCase): RouteTarget.objects.bulk_create(rts) l2vpns = ( - L2VPN(name='L2VPN 1', slug='l2vpn-1', type='vxlan', identifier='650001'), - L2VPN(name='L2VPN 2', slug='l2vpn-2', type='vxlan', identifier='650002'), - L2VPN(name='L2VPN 3', slug='l2vpn-3', type='vxlan', identifier='650003') + L2VPN(name='L2VPN 1', slug='l2vpn-1', type=L2VPNTypeChoices.TYPE_VXLAN, identifier='650001'), + L2VPN(name='L2VPN 2', slug='l2vpn-2', type=L2VPNTypeChoices.TYPE_VXLAN, identifier='650002'), + L2VPN(name='L2VPN 3', slug='l2vpn-3', type=L2VPNTypeChoices.TYPE_VXLAN, identifier='650003') ) L2VPN.objects.bulk_create(l2vpns) @@ -782,7 +778,7 @@ class L2VPNTestCase(ViewTestCases.PrimaryObjectViewTestCase): cls.form_data = { 'name': 'L2VPN 8', 'slug': 'l2vpn-8', - 'type': 'vxlan', + 'type': L2VPNTypeChoices.TYPE_VXLAN, 'identifier': 123, 'description': 'Description', 'import_targets': [rts[0].pk], @@ -805,21 +801,9 @@ class L2VPNTerminationTestCase( @classmethod def setUpTestData(cls): - site = Site.objects.create(name='Site 1') - manufacturer = Manufacturer.objects.create(name='Manufacturer 1') - device_type = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer) - device_role = DeviceRole.objects.create(name='Switch') - device = Device.objects.create( - name='Device 1', - site=site, - device_type=device_type, - device_role=device_role, - status='active' - ) - + device = create_test_device('Device 1') interface = Interface.objects.create(name='Interface 1', device=device, type='1000baset') - l2vpn = L2VPN.objects.create(name='L2VPN 1', type='vxlan', identifier=650001) - l2vpn_vlans = L2VPN.objects.create(name='L2VPN 2', type='vxlan', identifier=650002) + l2vpn = L2VPN.objects.create(name='L2VPN 1', type=L2VPNTypeChoices.TYPE_VXLAN, identifier=650001) vlans = ( VLAN(name='Vlan 1', vid=1001), @@ -846,9 +830,9 @@ class L2VPNTerminationTestCase( cls.csv_data = ( "l2vpn,vlan", - "L2VPN 2,Vlan 4", - "L2VPN 2,Vlan 5", - "L2VPN 2,Vlan 6", + "L2VPN 1,Vlan 4", + "L2VPN 1,Vlan 5", + "L2VPN 1,Vlan 6", ) cls.bulk_edit_data = {} @@ -857,6 +841,7 @@ class L2VPNTerminationTestCase( # Custom assertions # + # TODO: Remove this def assertInstanceEqual(self, instance, data, exclude=None, api=False): """ Override parent diff --git a/netbox/templates/ipam/l2vpn.html b/netbox/templates/ipam/l2vpn.html index 130940b02..44a1da818 100644 --- a/netbox/templates/ipam/l2vpn.html +++ b/netbox/templates/ipam/l2vpn.html @@ -6,46 +6,40 @@ {% block content %}
-
-
- L2VPN Attributes -
-
- Name - - - - - - - - - - - - - - - - - - - - - - -
{{ object.name|placeholder }}
Slug{{ object.slug|placeholder }}
Identifier{{ object.identifier|placeholder }}
Type{{ object.get_type_display }}
Description{{ object.description|placeholder }}
Tenant{{ object.tenant|placeholder }}
-
-
- {% include 'inc/panels/contacts.html' %} - {% plugin_left_page object %} +
+
L2VPN Attributes
+
+ + + + + + + + + + + + + + + + + + + + + +
Name{{ object.name|placeholder }}
Identifier{{ object.identifier|placeholder }}
Type{{ object.get_type_display }}
Description{{ object.description|placeholder }}
Tenant{{ object.tenant|linkify|placeholder }}
+
+
+ {% include 'inc/panels/tags.html' with tags=object.tags.all url='ipam:l2vpn_list' %} + {% plugin_left_page object %}
- {% include 'inc/panels/tags.html' with tags=object.tags.all url='circuits:circuit_list' %} - {% include 'inc/panels/custom_fields.html' %} - {% plugin_right_page object %} + {% include 'inc/panels/contacts.html' %} + {% include 'inc/panels/custom_fields.html' %} + {% plugin_right_page object %}
@@ -58,24 +52,24 @@
-
-
Terminations
-
- {% render_table terminations_table 'inc/table.html' %} -
- {% if perms.ipam.add_l2vpntermination %} - - {% endif %} +
+
Terminations
+
+ {% render_table terminations_table 'inc/table.html' %} +
+ {% if perms.ipam.add_l2vpntermination %} + + {% endif %}
+
-
- {% plugin_full_width_page object %} +
+ {% plugin_full_width_page object %}
{% endblock %} diff --git a/netbox/templates/ipam/l2vpntermination_edit.html b/netbox/templates/ipam/l2vpntermination_edit.html index 4ba079eb5..7b4a9f50a 100644 --- a/netbox/templates/ipam/l2vpntermination_edit.html +++ b/netbox/templates/ipam/l2vpntermination_edit.html @@ -18,12 +18,12 @@