|
|
@@ -13,10 +13,11 @@ 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, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
|
|
|
-from utilities.forms.rendering import FieldSet, InlineFields
|
|
|
+from utilities.forms.rendering import FieldSet, InlineFields, TabbedGroups
|
|
|
from utilities.forms.widgets import BulkEditNullBooleanSelect, NumberWithOptions
|
|
|
-from wireless.models import WirelessLAN, WirelessLANGroup
|
|
|
+from virtualization.models import Cluster
|
|
|
from wireless.choices import WirelessRoleChoices
|
|
|
+from wireless.models import WirelessLAN, WirelessLANGroup
|
|
|
|
|
|
__all__ = (
|
|
|
'CableBulkEditForm',
|
|
|
@@ -721,6 +722,14 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
queryset=ConfigTemplate.objects.all(),
|
|
|
required=False
|
|
|
)
|
|
|
+ cluster = DynamicModelChoiceField(
|
|
|
+ label=_('Cluster'),
|
|
|
+ queryset=Cluster.objects.all(),
|
|
|
+ required=False,
|
|
|
+ query_params={
|
|
|
+ 'site_id': ['$site', 'null']
|
|
|
+ },
|
|
|
+ )
|
|
|
comments = CommentField()
|
|
|
|
|
|
model = Device
|
|
|
@@ -729,9 +738,10 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
FieldSet('site', 'location', name=_('Location')),
|
|
|
FieldSet('manufacturer', 'device_type', 'airflow', 'serial', name=_('Hardware')),
|
|
|
FieldSet('config_template', name=_('Configuration')),
|
|
|
+ FieldSet('cluster', name=_('Virtualization')),
|
|
|
)
|
|
|
nullable_fields = (
|
|
|
- 'location', 'tenant', 'platform', 'serial', 'airflow', 'description', 'comments',
|
|
|
+ 'location', 'tenant', 'platform', 'serial', 'airflow', 'description', 'cluster', 'comments',
|
|
|
)
|
|
|
|
|
|
|
|
|
@@ -1404,18 +1414,25 @@ class InterfaceBulkEditForm(
|
|
|
parent = DynamicModelChoiceField(
|
|
|
label=_('Parent'),
|
|
|
queryset=Interface.objects.all(),
|
|
|
- required=False
|
|
|
+ required=False,
|
|
|
+ query_params={
|
|
|
+ 'virtual_chassis_member_id': '$device',
|
|
|
+ }
|
|
|
)
|
|
|
bridge = DynamicModelChoiceField(
|
|
|
label=_('Bridge'),
|
|
|
queryset=Interface.objects.all(),
|
|
|
- required=False
|
|
|
+ required=False,
|
|
|
+ query_params={
|
|
|
+ 'virtual_chassis_member_id': '$device',
|
|
|
+ }
|
|
|
)
|
|
|
lag = DynamicModelChoiceField(
|
|
|
queryset=Interface.objects.all(),
|
|
|
required=False,
|
|
|
query_params={
|
|
|
'type': 'lag',
|
|
|
+ 'virtual_chassis_member_id': '$device',
|
|
|
},
|
|
|
label=_('LAG')
|
|
|
)
|
|
|
@@ -1472,6 +1489,7 @@ class InterfaceBulkEditForm(
|
|
|
required=False,
|
|
|
query_params={
|
|
|
'group_id': '$vlan_group',
|
|
|
+ 'available_on_device': '$device',
|
|
|
},
|
|
|
label=_('Untagged VLAN')
|
|
|
)
|
|
|
@@ -1480,9 +1498,28 @@ class InterfaceBulkEditForm(
|
|
|
required=False,
|
|
|
query_params={
|
|
|
'group_id': '$vlan_group',
|
|
|
+ 'available_on_device': '$device',
|
|
|
},
|
|
|
label=_('Tagged VLANs')
|
|
|
)
|
|
|
+ add_tagged_vlans = DynamicModelMultipleChoiceField(
|
|
|
+ label=_('Add tagged VLANs'),
|
|
|
+ queryset=VLAN.objects.all(),
|
|
|
+ required=False,
|
|
|
+ query_params={
|
|
|
+ 'group_id': '$vlan_group',
|
|
|
+ 'available_on_device': '$device',
|
|
|
+ },
|
|
|
+ )
|
|
|
+ remove_tagged_vlans = DynamicModelMultipleChoiceField(
|
|
|
+ label=_('Remove tagged VLANs'),
|
|
|
+ queryset=VLAN.objects.all(),
|
|
|
+ required=False,
|
|
|
+ query_params={
|
|
|
+ 'group_id': '$vlan_group',
|
|
|
+ 'available_on_device': '$device',
|
|
|
+ }
|
|
|
+ )
|
|
|
vrf = DynamicModelChoiceField(
|
|
|
queryset=VRF.objects.all(),
|
|
|
required=False,
|
|
|
@@ -1509,7 +1546,13 @@ class InterfaceBulkEditForm(
|
|
|
FieldSet('vdcs', 'mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected', name=_('Operation')),
|
|
|
FieldSet('poe_mode', 'poe_type', name=_('PoE')),
|
|
|
FieldSet('parent', 'bridge', 'lag', name=_('Related Interfaces')),
|
|
|
- FieldSet('mode', 'vlan_group', 'untagged_vlan', 'tagged_vlans', name=_('802.1Q Switching')),
|
|
|
+ FieldSet('mode', 'vlan_group', 'untagged_vlan', name=_('802.1Q Switching')),
|
|
|
+ FieldSet(
|
|
|
+ TabbedGroups(
|
|
|
+ FieldSet('tagged_vlans', name=_('Assignment')),
|
|
|
+ FieldSet('add_tagged_vlans', 'remove_tagged_vlans', name=_('Add/Remove')),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
FieldSet(
|
|
|
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'wireless_lan_group', 'wireless_lans',
|
|
|
name=_('Wireless')
|
|
|
@@ -1523,19 +1566,7 @@ class InterfaceBulkEditForm(
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
super().__init__(*args, **kwargs)
|
|
|
- if self.device_id:
|
|
|
- device = Device.objects.filter(pk=self.device_id).first()
|
|
|
-
|
|
|
- # Restrict parent/bridge/LAG interface assignment by device
|
|
|
- self.fields['parent'].widget.add_query_param('virtual_chassis_member_id', device.pk)
|
|
|
- self.fields['bridge'].widget.add_query_param('virtual_chassis_member_id', device.pk)
|
|
|
- self.fields['lag'].widget.add_query_param('virtual_chassis_member_id', device.pk)
|
|
|
-
|
|
|
- # Limit VLAN choices by device
|
|
|
- self.fields['untagged_vlan'].widget.add_query_param('available_on_device', device.pk)
|
|
|
- self.fields['tagged_vlans'].widget.add_query_param('available_on_device', device.pk)
|
|
|
-
|
|
|
- else:
|
|
|
+ if not self.device_id:
|
|
|
# See #4523
|
|
|
if 'pk' in self.initial:
|
|
|
site = None
|
|
|
@@ -1559,6 +1590,13 @@ class InterfaceBulkEditForm(
|
|
|
'site_id', [site.pk, settings.FILTERS_NULL_CHOICE_VALUE]
|
|
|
)
|
|
|
|
|
|
+ self.fields['add_tagged_vlans'].widget.add_query_param(
|
|
|
+ 'site_id', [site.pk, settings.FILTERS_NULL_CHOICE_VALUE]
|
|
|
+ )
|
|
|
+ self.fields['remove_tagged_vlans'].widget.add_query_param(
|
|
|
+ 'site_id', [site.pk, settings.FILTERS_NULL_CHOICE_VALUE]
|
|
|
+ )
|
|
|
+
|
|
|
self.fields['parent'].choices = ()
|
|
|
self.fields['parent'].widget.attrs['disabled'] = True
|
|
|
self.fields['bridge'].choices = ()
|