1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #9177: Add tenant assignment for wireless LANs & links

This commit is contained in:
jeremystretch
2022-06-27 11:30:52 -04:00
parent f6c52e0616
commit 7dd5f9e720
21 changed files with 265 additions and 83 deletions

View File

@ -1,6 +1,6 @@
# Wireless LANs
A wireless LAN is a set of interfaces connected via a common wireless channel. Each instance must have an SSID, and may optionally be correlated to a VLAN. Wireless LANs can be arranged into hierarchical groups.
A wireless LAN is a set of interfaces connected via a common wireless channel. Each instance must have an SSID, and may optionally be correlated to a VLAN. Wireless LANs can be arranged into hierarchical groups, and each may be associated with a particular tenant.
An interface may be attached to multiple wireless LANs, provided they are all operating on the same channel. Only wireless interfaces may be attached to wireless LANs.

View File

@ -1,6 +1,6 @@
# Wireless Links
A wireless link represents a connection between exactly two wireless interfaces. It may optionally be assigned an SSID and a description. It may also have a status assigned to it, similar to the cable model.
A wireless link represents a connection between exactly two wireless interfaces. It may optionally be assigned an SSID and a description. It may also have a status assigned to it, similar to the cable model. Each wireless link may also be assigned to a particular tenant.
Each wireless link may have authentication attributes associated with it, including:

View File

@ -28,6 +28,7 @@
* [#8495](https://github.com/netbox-community/netbox/issues/8495) - Enable custom field grouping
* [#8995](https://github.com/netbox-community/netbox/issues/8995) - Enable arbitrary ordering of REST API results
* [#9166](https://github.com/netbox-community/netbox/issues/9166) - Add UI visibility toggle for custom fields
* [#9177](https://github.com/netbox-community/netbox/issues/9177) - Add tenant assignment for wireless LANs & links
* [#9536](https://github.com/netbox-community/netbox/issues/9536) - Track API token usage times
* [#9582](https://github.com/netbox-community/netbox/issues/9582) - Enable assigning config contexts based on device location
@ -70,3 +71,7 @@
* Added `device` field
* The `site` field is now directly writable (rather than being inferred from the assigned cluster)
* The `cluster` field is now optional. A virtual machine must have a site and/or cluster assigned.
wireless.WirelessLAN
* Added `tenant` field
wireless.WirelessLink
* Added `tenant` field

View File

@ -61,6 +61,10 @@
<h2><a href="{% url 'dcim:device_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.device_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.device_count }}</a></h2>
<p>Devices</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'dcim:cable_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.cable_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.cable_count }}</a></h2>
<p>Cables</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'ipam:vrf_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.vrf_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.vrf_count }}</a></h2>
<p>VRFs</p>
@ -102,8 +106,12 @@
<p>Clusters</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'dcim:cable_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.cable_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.cable_count }}</a></h2>
<p>Cables</p>
<h2><a href="{% url 'wireless:wirelesslan_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.wirelesslan_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.wirelesslan_count }}</a></h2>
<p>Wireless LANs</p>
</div>
<div class="col col-md-4 text-center">
<h2><a href="{% url 'wireless:wirelesslink_list' %}?tenant_id={{ object.pk }}" class="stat-btn btn {% if stats.wirelesslink_count %}btn-primary{% else %}btn-outline-dark{% endif %} btn-lg">{{ stats.wirelesslink_count }}</a></h2>
<p>Wireless Links</p>
</div>
</div>
</div>

View File

@ -6,36 +6,45 @@
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">Wireless LAN</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">SSID</th>
<td>{{ object.ssid }}</td>
</tr>
<tr>
<td>Group</td>
<td>{{ object.group|linkify|placeholder }}</td>
</tr>
<tr>
<th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td>
</tr>
<tr>
<th scope="row">VLAN</th>
<td>{{ object.vlan|linkify|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
<div class="card">
<h5 class="card-header">Wireless LAN</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">SSID</th>
<td>{{ object.ssid }}</td>
</tr>
<tr>
<td>Group</td>
<td>{{ object.group|linkify|placeholder }}</td>
</tr>
<tr>
<th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td>
</tr>
<tr>
<th scope="row">VLAN</th>
<td>{{ object.vlan|linkify|placeholder }}</td>
</tr>
<tr>
<th scope="row">Tenant</th>
<td>
{% if object.tenant.group %}
{{ object.tenant.group|linkify }} /
{% endif %}
{{ object.tenant|linkify|placeholder }}
</td>
</tr>
</table>
</div>
</div>
<div class="col col-md-6">
{% include 'wireless/inc/authentication_attrs.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
{% include 'inc/panels/tags.html' %}
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
{% include 'wireless/inc/authentication_attrs.html' %}
{% include 'inc/panels/custom_fields.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">

View File

@ -23,6 +23,15 @@
<th scope="row">SSID</th>
<td>{{ object.ssid|placeholder }}</td>
</tr>
<tr>
<th scope="row">Tenant</th>
<td>
{% if object.tenant.group %}
{{ object.tenant.group|linkify }} /
{% endif %}
{{ object.tenant|linkify|placeholder }}
</td>
</tr>
<tr>
<th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td>

View File

@ -7,6 +7,7 @@ from ipam.models import Aggregate, IPAddress, IPRange, Prefix, VLAN, VRF, ASN
from netbox.views import generic
from utilities.utils import count_related
from virtualization.models import VirtualMachine, Cluster
from wireless.models import WirelessLAN, WirelessLink
from . import filtersets, forms, tables
from .models import *
@ -114,6 +115,8 @@ class TenantView(generic.ObjectView):
'cluster_count': Cluster.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'cable_count': Cable.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'asn_count': ASN.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'wirelesslan_count': WirelessLAN.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
'wirelesslink_count': WirelessLink.objects.restrict(request.user, 'view').filter(tenant=instance).count(),
}
return {

View File

@ -5,6 +5,7 @@ from dcim.api.serializers import NestedInterfaceSerializer
from ipam.api.serializers import NestedVLANSerializer
from netbox.api import ChoiceField
from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
from tenancy.api.nested_serializers import NestedTenantSerializer
from wireless.choices import *
from wireless.models import *
from .nested_serializers import *
@ -33,14 +34,15 @@ class WirelessLANSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail')
group = NestedWirelessLANGroupSerializer(required=False, allow_null=True)
vlan = NestedVLANSerializer(required=False, allow_null=True)
tenant = NestedTenantSerializer(required=False, allow_null=True)
auth_type = ChoiceField(choices=WirelessAuthTypeChoices, required=False, allow_blank=True)
auth_cipher = ChoiceField(choices=WirelessAuthCipherChoices, required=False, allow_blank=True)
class Meta:
model = WirelessLAN
fields = [
'id', 'url', 'display', 'ssid', 'description', 'group', 'vlan', 'auth_type', 'auth_cipher', 'auth_psk',
'description', 'tags', 'custom_fields', 'created', 'last_updated',
'id', 'url', 'display', 'ssid', 'description', 'group', 'vlan', 'tenant', 'auth_type', 'auth_cipher',
'auth_psk', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
]
@ -49,12 +51,13 @@ class WirelessLinkSerializer(NetBoxModelSerializer):
status = ChoiceField(choices=LinkStatusChoices, required=False)
interface_a = NestedInterfaceSerializer()
interface_b = NestedInterfaceSerializer()
tenant = NestedTenantSerializer(required=False, allow_null=True)
auth_type = ChoiceField(choices=WirelessAuthTypeChoices, required=False, allow_blank=True)
auth_cipher = ChoiceField(choices=WirelessAuthCipherChoices, required=False, allow_blank=True)
class Meta:
model = WirelessLink
fields = [
'id', 'url', 'display', 'interface_a', 'interface_b', 'ssid', 'status', 'description', 'auth_type',
'id', 'url', 'display', 'interface_a', 'interface_b', 'ssid', 'status', 'tenant', 'auth_type',
'auth_cipher', 'auth_psk', 'description', 'tags', 'custom_fields', 'created', 'last_updated',
]

View File

@ -27,12 +27,12 @@ class WirelessLANGroupViewSet(NetBoxModelViewSet):
class WirelessLANViewSet(NetBoxModelViewSet):
queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags')
queryset = WirelessLAN.objects.prefetch_related('vlan', 'tenant', 'tags')
serializer_class = serializers.WirelessLANSerializer
filterset_class = filtersets.WirelessLANFilterSet
class WirelessLinkViewSet(NetBoxModelViewSet):
queryset = WirelessLink.objects.prefetch_related('interface_a', 'interface_b', 'tags')
queryset = WirelessLink.objects.prefetch_related('interface_a', 'interface_b', 'tenant', 'tags')
serializer_class = serializers.WirelessLinkSerializer
filterset_class = filtersets.WirelessLinkFilterSet

View File

@ -4,6 +4,7 @@ from django.db.models import Q
from dcim.choices import LinkStatusChoices
from ipam.models import VLAN
from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
from tenancy.filtersets import TenancyFilterSet
from utilities.filters import MultiValueNumberFilter, TreeNodeMultipleChoiceFilter
from .choices import *
from .models import *
@ -30,7 +31,7 @@ class WirelessLANGroupFilterSet(OrganizationalModelFilterSet):
fields = ['id', 'name', 'slug', 'description']
class WirelessLANFilterSet(NetBoxModelFilterSet):
class WirelessLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
group_id = TreeNodeMultipleChoiceFilter(
queryset=WirelessLANGroup.objects.all(),
field_name='group',
@ -66,7 +67,7 @@ class WirelessLANFilterSet(NetBoxModelFilterSet):
return queryset.filter(qs_filter)
class WirelessLinkFilterSet(NetBoxModelFilterSet):
class WirelessLinkFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
interface_a_id = MultiValueNumberFilter()
interface_b_id = MultiValueNumberFilter()
status = django_filters.MultipleChoiceFilter(

View File

@ -3,6 +3,7 @@ from django import forms
from dcim.choices import LinkStatusChoices
from ipam.models import VLAN
from netbox.forms import NetBoxModelBulkEditForm
from tenancy.models import Tenant
from utilities.forms import add_blank_choice, DynamicModelChoiceField
from wireless.choices import *
from wireless.constants import SSID_MAX_LENGTH
@ -47,6 +48,10 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
required=False,
label='SSID'
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False
)
description = forms.CharField(
required=False
)
@ -65,11 +70,11 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
model = WirelessLAN
fieldsets = (
(None, ('group', 'vlan', 'ssid', 'description')),
(None, ('group', 'ssid', 'vlan', 'tenant', 'description')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
)
nullable_fields = (
'ssid', 'group', 'vlan', 'description', 'auth_type', 'auth_cipher', 'auth_psk',
'ssid', 'group', 'vlan', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk',
)
@ -83,6 +88,10 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
choices=add_blank_choice(LinkStatusChoices),
required=False
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
required=False
)
description = forms.CharField(
required=False
)
@ -101,9 +110,9 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
model = WirelessLink
fieldsets = (
(None, ('ssid', 'status', 'description')),
(None, ('ssid', 'status', 'tenant', 'description')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk'))
)
nullable_fields = (
'ssid', 'description', 'auth_type', 'auth_cipher', 'auth_psk',
'ssid', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk',
)

View File

@ -2,6 +2,7 @@ from dcim.choices import LinkStatusChoices
from dcim.models import Interface
from ipam.models import VLAN
from netbox.forms import NetBoxModelCSVForm
from tenancy.models import Tenant
from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField
from wireless.choices import *
from wireless.models import *
@ -40,6 +41,12 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
to_field_name='name',
help_text='Bridged VLAN'
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
help_text='Assigned tenant'
)
auth_type = CSVChoiceField(
choices=WirelessAuthTypeChoices,
required=False,
@ -53,7 +60,7 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
class Meta:
model = WirelessLAN
fields = ('ssid', 'group', 'description', 'vlan', 'auth_type', 'auth_cipher', 'auth_psk')
fields = ('ssid', 'group', 'vlan', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk')
class WirelessLinkCSVForm(NetBoxModelCSVForm):
@ -67,6 +74,12 @@ class WirelessLinkCSVForm(NetBoxModelCSVForm):
interface_b = CSVModelChoiceField(
queryset=Interface.objects.all()
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
help_text='Assigned tenant'
)
auth_type = CSVChoiceField(
choices=WirelessAuthTypeChoices,
required=False,
@ -80,4 +93,6 @@ class WirelessLinkCSVForm(NetBoxModelCSVForm):
class Meta:
model = WirelessLink
fields = ('interface_a', 'interface_b', 'ssid', 'description', 'auth_type', 'auth_cipher', 'auth_psk')
fields = (
'interface_a', 'interface_b', 'ssid', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk',
)

View File

@ -3,6 +3,7 @@ from django.utils.translation import gettext as _
from dcim.choices import LinkStatusChoices
from netbox.forms import NetBoxModelFilterSetForm
from tenancy.forms import TenancyFilterForm
from utilities.forms import add_blank_choice, DynamicModelMultipleChoiceField, StaticSelect, TagFilterField
from wireless.choices import *
from wireless.models import *
@ -24,11 +25,12 @@ class WirelessLANGroupFilterForm(NetBoxModelFilterSetForm):
tag = TagFilterField(model)
class WirelessLANFilterForm(NetBoxModelFilterSetForm):
class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = WirelessLAN
fieldsets = (
(None, ('q', 'tag')),
('Attributes', ('ssid', 'group_id',)),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
)
ssid = forms.CharField(
@ -57,8 +59,14 @@ class WirelessLANFilterForm(NetBoxModelFilterSetForm):
tag = TagFilterField(model)
class WirelessLinkFilterForm(NetBoxModelFilterSetForm):
class WirelessLinkFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
model = WirelessLink
fieldsets = (
(None, ('q', 'tag')),
('Attributes', ('ssid', 'status',)),
('Tenant', ('tenant_group_id', 'tenant_id')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
)
ssid = forms.CharField(
required=False,
label='SSID'

View File

@ -1,6 +1,7 @@
from dcim.models import Device, Interface, Location, Region, Site, SiteGroup
from ipam.models import VLAN, VLANGroup
from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm
from utilities.forms import DynamicModelChoiceField, SlugField, StaticSelect
from wireless.models import *
@ -25,7 +26,7 @@ class WirelessLANGroupForm(NetBoxModelForm):
]
class WirelessLANForm(NetBoxModelForm):
class WirelessLANForm(TenancyForm, NetBoxModelForm):
group = DynamicModelChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False
@ -79,14 +80,15 @@ class WirelessLANForm(NetBoxModelForm):
fieldsets = (
('Wireless LAN', ('ssid', 'group', 'description', 'tags')),
('VLAN', ('region', 'site_group', 'site', 'vlan_group', 'vlan',)),
('Tenancy', ('tenant_group', 'tenant')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
)
class Meta:
model = WirelessLAN
fields = [
'ssid', 'group', 'description', 'region', 'site_group', 'site', 'vlan_group', 'vlan', 'auth_type',
'auth_cipher', 'auth_psk', 'tags',
'ssid', 'group', 'description', 'region', 'site_group', 'site', 'vlan_group', 'vlan', 'tenant_group',
'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'tags',
]
widgets = {
'auth_type': StaticSelect,
@ -94,7 +96,7 @@ class WirelessLANForm(NetBoxModelForm):
}
class WirelessLinkForm(NetBoxModelForm):
class WirelessLinkForm(TenancyForm, NetBoxModelForm):
site_a = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
@ -180,6 +182,7 @@ class WirelessLinkForm(NetBoxModelForm):
('Side A', ('site_a', 'location_a', 'device_a', 'interface_a')),
('Side B', ('site_b', 'location_b', 'device_b', 'interface_b')),
('Link', ('status', 'ssid', 'description', 'tags')),
('Tenancy', ('tenant_group', 'tenant')),
('Authentication', ('auth_type', 'auth_cipher', 'auth_psk')),
)
@ -187,7 +190,7 @@ class WirelessLinkForm(NetBoxModelForm):
model = WirelessLink
fields = [
'site_a', 'location_a', 'device_a', 'interface_a', 'site_b', 'location_b', 'device_b', 'interface_b',
'status', 'ssid', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'tags',
'status', 'ssid', 'tenant_group', 'tenant', 'description', 'auth_type', 'auth_cipher', 'auth_psk', 'tags',
]
widgets = {
'status': StaticSelect,

View File

@ -0,0 +1,25 @@
# Generated by Django 4.0.5 on 2022-06-27 13:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tenancy', '0007_contact_link'),
('wireless', '0003_created_datetimefield'),
]
operations = [
migrations.AddField(
model_name='wirelesslan',
name='tenant',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wireless_lans', to='tenancy.tenant'),
),
migrations.AddField(
model_name='wirelesslink',
name='tenant',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='wireless_links', to='tenancy.tenant'),
),
]

View File

@ -101,6 +101,13 @@ class WirelessLAN(WirelessAuthenticationBase, NetBoxModel):
null=True,
verbose_name='VLAN'
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
on_delete=models.PROTECT,
related_name='wireless_lans',
blank=True,
null=True
)
description = models.CharField(
max_length=200,
blank=True
@ -143,6 +150,13 @@ class WirelessLink(WirelessAuthenticationBase, NetBoxModel):
choices=LinkStatusChoices,
default=LinkStatusChoices.STATUS_CONNECTED
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
on_delete=models.PROTECT,
related_name='wireless_links',
blank=True,
null=True
)
description = models.CharField(
max_length=200,
blank=True

View File

@ -2,6 +2,7 @@ import django_tables2 as tables
from dcim.models import Interface
from netbox.tables import NetBoxTable, columns
from tenancy.tables import TenantColumn
from wireless.models import *
__all__ = (
@ -39,6 +40,7 @@ class WirelessLANTable(NetBoxTable):
group = tables.Column(
linkify=True
)
tenant = TenantColumn()
interface_count = tables.Column(
verbose_name='Interfaces'
)
@ -49,8 +51,8 @@ class WirelessLANTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = WirelessLAN
fields = (
'pk', 'ssid', 'group', 'description', 'vlan', 'interface_count', 'auth_type', 'auth_cipher', 'auth_psk',
'tags', 'created', 'last_updated',
'pk', 'ssid', 'group', 'tenant', 'description', 'vlan', 'interface_count', 'auth_type', 'auth_cipher',
'auth_psk', 'tags', 'created', 'last_updated',
)
default_columns = ('pk', 'ssid', 'group', 'description', 'vlan', 'auth_type', 'interface_count')

View File

@ -1,6 +1,7 @@
import django_tables2 as tables
from netbox.tables import NetBoxTable, columns
from tenancy.tables import TenantColumn
from wireless.models import *
__all__ = (
@ -28,6 +29,7 @@ class WirelessLinkTable(NetBoxTable):
interface_b = tables.Column(
linkify=True
)
tenant = TenantColumn()
tags = columns.TagColumn(
url_name='wireless:wirelesslink_list'
)
@ -35,7 +37,7 @@ class WirelessLinkTable(NetBoxTable):
class Meta(NetBoxTable.Meta):
model = WirelessLink
fields = (
'pk', 'id', 'status', 'device_a', 'interface_a', 'device_b', 'interface_b', 'ssid', 'description',
'pk', 'id', 'status', 'device_a', 'interface_a', 'device_b', 'interface_b', 'ssid', 'tenant', 'description',
'auth_type', 'auth_cipher', 'auth_psk', 'tags', 'created', 'last_updated',
)
default_columns = (

View File

@ -1,10 +1,11 @@
from django.urls import reverse
from wireless.choices import *
from wireless.models import *
from dcim.choices import InterfaceTypeChoices
from dcim.models import Interface
from tenancy.models import Tenant
from utilities.testing import APITestCase, APIViewTestCases, create_test_device
from wireless.choices import *
from wireless.models import *
class AppTest(APITestCase):
@ -52,6 +53,12 @@ class WirelessLANTest(APIViewTestCases.APIViewTestCase):
@classmethod
def setUpTestData(cls):
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
)
Tenant.objects.bulk_create(tenants)
groups = (
WirelessLANGroup(name='Group 1', slug='group-1'),
WirelessLANGroup(name='Group 2', slug='group-2'),
@ -71,21 +78,25 @@ class WirelessLANTest(APIViewTestCases.APIViewTestCase):
{
'ssid': 'WLAN4',
'group': groups[0].pk,
'tenant': tenants[0].pk,
'auth_type': WirelessAuthTypeChoices.TYPE_OPEN,
},
{
'ssid': 'WLAN5',
'group': groups[1].pk,
'tenant': tenants[0].pk,
'auth_type': WirelessAuthTypeChoices.TYPE_WPA_PERSONAL,
},
{
'ssid': 'WLAN6',
'tenant': tenants[0].pk,
'auth_type': WirelessAuthTypeChoices.TYPE_WPA_ENTERPRISE,
},
]
cls.bulk_update_data = {
'group': groups[2].pk,
'tenant': tenants[1].pk,
'description': 'New description',
'auth_type': WirelessAuthTypeChoices.TYPE_WPA_PERSONAL,
'auth_cipher': WirelessAuthCipherChoices.CIPHER_AES,
@ -115,10 +126,16 @@ class WirelessLinkTest(APIViewTestCases.APIViewTestCase):
]
Interface.objects.bulk_create(interfaces)
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
)
Tenant.objects.bulk_create(tenants)
wireless_links = (
WirelessLink(ssid='LINK1', interface_a=interfaces[0], interface_b=interfaces[1]),
WirelessLink(ssid='LINK2', interface_a=interfaces[2], interface_b=interfaces[3]),
WirelessLink(ssid='LINK3', interface_a=interfaces[4], interface_b=interfaces[5]),
WirelessLink(ssid='LINK1', interface_a=interfaces[0], interface_b=interfaces[1], tenant=tenants[0]),
WirelessLink(ssid='LINK2', interface_a=interfaces[2], interface_b=interfaces[3], tenant=tenants[0]),
WirelessLink(ssid='LINK3', interface_a=interfaces[4], interface_b=interfaces[5], tenant=tenants[0]),
)
WirelessLink.objects.bulk_create(wireless_links)
@ -127,15 +144,18 @@ class WirelessLinkTest(APIViewTestCases.APIViewTestCase):
'interface_a': interfaces[6].pk,
'interface_b': interfaces[7].pk,
'ssid': 'LINK4',
'tenant': tenants[1].pk,
},
{
'interface_a': interfaces[8].pk,
'interface_b': interfaces[9].pk,
'ssid': 'LINK5',
'tenant': tenants[1].pk,
},
{
'interface_a': interfaces[10].pk,
'interface_b': interfaces[11].pk,
'ssid': 'LINK6',
'tenant': tenants[1].pk,
},
]

View File

@ -3,6 +3,7 @@ from django.test import TestCase
from dcim.choices import InterfaceTypeChoices, LinkStatusChoices
from dcim.models import Interface
from ipam.models import VLAN
from tenancy.models import Tenant
from wireless.choices import *
from wireless.filtersets import *
from wireless.models import *
@ -43,10 +44,6 @@ class WirelessLANGroupTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'slug': ['wireless-lan-group-1', 'wireless-lan-group-2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_description(self):
params = {'description': ['A', 'B']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_parent(self):
parent_groups = WirelessLANGroup.objects.filter(parent__isnull=True)[:2]
params = {'parent_id': [parent_groups[0].pk, parent_groups[1].pk]}
@ -81,10 +78,17 @@ class WirelessLANTestCase(TestCase, ChangeLoggedFilterSetTests):
)
VLAN.objects.bulk_create(vlans)
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
Tenant(name='Tenant 3', slug='tenant-3'),
)
Tenant.objects.bulk_create(tenants)
wireless_lans = (
WirelessLAN(ssid='WLAN1', group=groups[0], vlan=vlans[0], auth_type=WirelessAuthTypeChoices.TYPE_OPEN, auth_cipher=WirelessAuthCipherChoices.CIPHER_AUTO, auth_psk='PSK1'),
WirelessLAN(ssid='WLAN2', group=groups[1], vlan=vlans[1], auth_type=WirelessAuthTypeChoices.TYPE_WEP, auth_cipher=WirelessAuthCipherChoices.CIPHER_TKIP, auth_psk='PSK2'),
WirelessLAN(ssid='WLAN3', group=groups[2], vlan=vlans[2], auth_type=WirelessAuthTypeChoices.TYPE_WPA_PERSONAL, auth_cipher=WirelessAuthCipherChoices.CIPHER_AES, auth_psk='PSK3'),
WirelessLAN(ssid='WLAN1', group=groups[0], vlan=vlans[0], tenant=tenants[0], auth_type=WirelessAuthTypeChoices.TYPE_OPEN, auth_cipher=WirelessAuthCipherChoices.CIPHER_AUTO, auth_psk='PSK1'),
WirelessLAN(ssid='WLAN2', group=groups[1], vlan=vlans[1], tenant=tenants[1], auth_type=WirelessAuthTypeChoices.TYPE_WEP, auth_cipher=WirelessAuthCipherChoices.CIPHER_TKIP, auth_psk='PSK2'),
WirelessLAN(ssid='WLAN3', group=groups[2], vlan=vlans[2], tenant=tenants[2], auth_type=WirelessAuthTypeChoices.TYPE_WPA_PERSONAL, auth_cipher=WirelessAuthCipherChoices.CIPHER_AES, auth_psk='PSK3'),
)
WirelessLAN.objects.bulk_create(wireless_lans)
@ -116,6 +120,13 @@ class WirelessLANTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'auth_psk': ['PSK1', 'PSK2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_tenant(self):
tenants = Tenant.objects.all()[:2]
params = {'tenant_id': [tenants[0].pk, tenants[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'tenant': [tenants[0].slug, tenants[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = WirelessLink.objects.all()
@ -124,6 +135,13 @@ class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
@classmethod
def setUpTestData(cls):
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
Tenant(name='Tenant 3', slug='tenant-3'),
)
Tenant.objects.bulk_create(tenants)
devices = (
create_test_device('device1'),
create_test_device('device2'),
@ -152,6 +170,7 @@ class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
auth_type=WirelessAuthTypeChoices.TYPE_OPEN,
auth_cipher=WirelessAuthCipherChoices.CIPHER_AUTO,
auth_psk='PSK1',
tenant=tenants[0],
description='foobar1'
).save()
WirelessLink(
@ -162,6 +181,7 @@ class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
auth_type=WirelessAuthTypeChoices.TYPE_WEP,
auth_cipher=WirelessAuthCipherChoices.CIPHER_TKIP,
auth_psk='PSK2',
tenant=tenants[1],
description='foobar2'
).save()
WirelessLink(
@ -171,7 +191,8 @@ class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
status=LinkStatusChoices.STATUS_DECOMMISSIONING,
auth_type=WirelessAuthTypeChoices.TYPE_WPA_PERSONAL,
auth_cipher=WirelessAuthCipherChoices.CIPHER_AES,
auth_psk='PSK3'
auth_psk='PSK3',
tenant=tenants[2],
).save()
WirelessLink(
interface_a=interfaces[5],
@ -202,3 +223,10 @@ class WirelessLinkTestCase(TestCase, ChangeLoggedFilterSetTests):
def test_description(self):
params = {'description': ['foobar1', 'foobar2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_tenant(self):
tenants = Tenant.objects.all()[:2]
params = {'tenant_id': [tenants[0].pk, tenants[1].pk]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
params = {'tenant': [tenants[0].slug, tenants[1].slug]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

View File

@ -2,6 +2,7 @@ from wireless.choices import *
from wireless.models import *
from dcim.choices import InterfaceTypeChoices, LinkStatusChoices
from dcim.models import Interface
from tenancy.models import Tenant
from utilities.testing import ViewTestCases, create_tags, create_test_device
@ -47,6 +48,13 @@ class WirelessLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
@classmethod
def setUpTestData(cls):
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
Tenant(name='Tenant 3', slug='tenant-3'),
)
Tenant.objects.bulk_create(tenants)
groups = (
WirelessLANGroup(name='Wireless LAN Group 1', slug='wireless-lan-group-1'),
WirelessLANGroup(name='Wireless LAN Group 2', slug='wireless-lan-group-2'),
@ -55,9 +63,9 @@ class WirelessLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
group.save()
WirelessLAN.objects.bulk_create([
WirelessLAN(group=groups[0], ssid='WLAN1'),
WirelessLAN(group=groups[0], ssid='WLAN2'),
WirelessLAN(group=groups[0], ssid='WLAN3'),
WirelessLAN(group=groups[0], ssid='WLAN1', tenant=tenants[0]),
WirelessLAN(group=groups[0], ssid='WLAN2', tenant=tenants[0]),
WirelessLAN(group=groups[0], ssid='WLAN3', tenant=tenants[0]),
])
tags = create_tags('Alpha', 'Bravo', 'Charlie')
@ -65,14 +73,15 @@ class WirelessLANTestCase(ViewTestCases.PrimaryObjectViewTestCase):
cls.form_data = {
'ssid': 'WLAN2',
'group': groups[1].pk,
'tenant': tenants[1].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"group,ssid",
"Wireless LAN Group 2,WLAN4",
"Wireless LAN Group 2,WLAN5",
"Wireless LAN Group 2,WLAN6",
f"group,ssid,tenant",
f"Wireless LAN Group 2,WLAN4,{tenants[0].name}",
f"Wireless LAN Group 2,WLAN5,{tenants[1].name}",
f"Wireless LAN Group 2,WLAN6,{tenants[2].name}",
)
cls.bulk_edit_data = {
@ -85,6 +94,14 @@ class WirelessLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
@classmethod
def setUpTestData(cls):
tenants = (
Tenant(name='Tenant 1', slug='tenant-1'),
Tenant(name='Tenant 2', slug='tenant-2'),
Tenant(name='Tenant 3', slug='tenant-3'),
)
Tenant.objects.bulk_create(tenants)
device = create_test_device('test-device')
interfaces = [
Interface(
@ -98,9 +115,9 @@ class WirelessLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
]
Interface.objects.bulk_create(interfaces)
WirelessLink(interface_a=interfaces[0], interface_b=interfaces[1], ssid='LINK1').save()
WirelessLink(interface_a=interfaces[2], interface_b=interfaces[3], ssid='LINK2').save()
WirelessLink(interface_a=interfaces[4], interface_b=interfaces[5], ssid='LINK3').save()
WirelessLink(interface_a=interfaces[0], interface_b=interfaces[1], ssid='LINK1', tenant=tenants[0]).save()
WirelessLink(interface_a=interfaces[2], interface_b=interfaces[3], ssid='LINK2', tenant=tenants[0]).save()
WirelessLink(interface_a=interfaces[4], interface_b=interfaces[5], ssid='LINK3', tenant=tenants[0]).save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
@ -108,14 +125,15 @@ class WirelessLinkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'interface_a': interfaces[6].pk,
'interface_b': interfaces[7].pk,
'status': LinkStatusChoices.STATUS_PLANNED,
'tenant': tenants[1].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"interface_a,interface_b,status",
f"{interfaces[6].pk},{interfaces[7].pk},connected",
f"{interfaces[8].pk},{interfaces[9].pk},connected",
f"{interfaces[10].pk},{interfaces[11].pk},connected",
f"interface_a,interface_b,status,tenant",
f"{interfaces[6].pk},{interfaces[7].pk},connected,{tenants[0].name}",
f"{interfaces[8].pk},{interfaces[9].pk},connected,{tenants[1].name}",
f"{interfaces[10].pk},{interfaces[11].pk},connected,{tenants[2].name}",
)
cls.bulk_edit_data = {