|
@@ -23,8 +23,9 @@ from tenancy.models import Tenant, TenantGroup
|
|
|
from utilities.forms import (
|
|
from utilities.forms import (
|
|
|
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
|
|
APISelect, APISelectMultiple, add_blank_choice, ArrayFieldSelectMultiple, BootstrapMixin, BulkEditForm,
|
|
|
BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField,
|
|
BulkEditNullBooleanSelect, ColorSelect, CommentField, ConfirmationForm, CSVChoiceField, DynamicModelChoiceField,
|
|
|
- DynamicModelMultipleChoiceField, ExpandableNameField, FlexibleModelChoiceField, JSONField, SelectWithPK,
|
|
|
|
|
- SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
|
|
|
|
|
|
|
+ DynamicModelMultipleChoiceField, ExpandableNameField, FlexibleModelChoiceField, form_from_model, JSONField,
|
|
|
|
|
+ SelectWithPK, SmallTextarea, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField,
|
|
|
|
|
+ BOOLEAN_WITH_BLANK_CHOICES,
|
|
|
)
|
|
)
|
|
|
from virtualization.models import Cluster, ClusterGroup, VirtualMachine
|
|
from virtualization.models import Cluster, ClusterGroup, VirtualMachine
|
|
|
from .choices import *
|
|
from .choices import *
|
|
@@ -2298,30 +2299,10 @@ class DeviceBulkAddComponentForm(BootstrapMixin, forms.Form):
|
|
|
label='Name'
|
|
label='Name'
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBulkAddInterfaceForm(DeviceBulkAddComponentForm):
|
|
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=InterfaceTypeChoices,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- enabled = forms.BooleanField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- initial=True
|
|
|
|
|
- )
|
|
|
|
|
- mtu = forms.IntegerField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- min_value=INTERFACE_MTU_MIN,
|
|
|
|
|
- max_value=INTERFACE_MTU_MAX,
|
|
|
|
|
- label='MTU'
|
|
|
|
|
- )
|
|
|
|
|
- mgmt_only = forms.BooleanField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- label='Management only'
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ def clean_tags(self):
|
|
|
|
|
+ # Because we're feeding TagField data (on the bulk edit form) to another TagField (on the model form), we
|
|
|
|
|
+ # must first convert the list of tags to a string.
|
|
|
|
|
+ return ','.join(self.cleaned_data.get('tags'))
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
#
|
|
@@ -2375,20 +2356,23 @@ class ConsolePortCreateForm(BootstrapMixin, forms.Form):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-class ConsolePortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
|
|
+class ConsolePortBulkCreateForm(
|
|
|
|
|
+ form_from_model(ConsolePort, ['type', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class ConsolePortBulkEditForm(
|
|
|
|
|
+ form_from_model(ConsolePort, ['type', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
pk = forms.ModelMultipleChoiceField(
|
|
pk = forms.ModelMultipleChoiceField(
|
|
|
queryset=ConsolePort.objects.all(),
|
|
queryset=ConsolePort.objects.all(),
|
|
|
widget=forms.MultipleHiddenInput()
|
|
widget=forms.MultipleHiddenInput()
|
|
|
)
|
|
)
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(ConsolePortTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
class Meta:
|
|
|
nullable_fields = (
|
|
nullable_fields = (
|
|
@@ -2462,20 +2446,23 @@ class ConsoleServerPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-class ConsoleServerPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
|
|
+class ConsoleServerPortBulkCreateForm(
|
|
|
|
|
+ form_from_model(ConsoleServerPort, ['type', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class ConsoleServerPortBulkEditForm(
|
|
|
|
|
+ form_from_model(ConsoleServerPort, ['type', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
pk = forms.ModelMultipleChoiceField(
|
|
pk = forms.ModelMultipleChoiceField(
|
|
|
queryset=ConsoleServerPort.objects.all(),
|
|
queryset=ConsoleServerPort.objects.all(),
|
|
|
widget=forms.MultipleHiddenInput()
|
|
widget=forms.MultipleHiddenInput()
|
|
|
)
|
|
)
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(ConsolePortTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
class Meta:
|
|
|
nullable_fields = [
|
|
nullable_fields = [
|
|
@@ -2573,30 +2560,23 @@ class PowerPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-class PowerPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
|
|
+class PowerPortBulkCreateForm(
|
|
|
|
|
+ form_from_model(PowerPort, ['type', 'maximum_draw', 'allocated_draw', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class PowerPortBulkEditForm(
|
|
|
|
|
+ form_from_model(PowerPort, ['type', 'maximum_draw', 'allocated_draw', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
pk = forms.ModelMultipleChoiceField(
|
|
pk = forms.ModelMultipleChoiceField(
|
|
|
queryset=PowerPort.objects.all(),
|
|
queryset=PowerPort.objects.all(),
|
|
|
widget=forms.MultipleHiddenInput()
|
|
widget=forms.MultipleHiddenInput()
|
|
|
)
|
|
)
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(PowerPortTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- maximum_draw = forms.IntegerField(
|
|
|
|
|
- min_value=1,
|
|
|
|
|
- required=False,
|
|
|
|
|
- help_text="Maximum draw in watts"
|
|
|
|
|
- )
|
|
|
|
|
- allocated_draw = forms.IntegerField(
|
|
|
|
|
- min_value=1,
|
|
|
|
|
- required=False,
|
|
|
|
|
- help_text="Allocated draw in watts"
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
class Meta:
|
|
|
nullable_fields = (
|
|
nullable_fields = (
|
|
@@ -2700,6 +2680,61 @@ class PowerOutletCreateForm(BootstrapMixin, forms.Form):
|
|
|
self.fields['power_port'].queryset = PowerPort.objects.filter(device=device)
|
|
self.fields['power_port'].queryset = PowerPort.objects.filter(device=device)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+class PowerOutletBulkCreateForm(
|
|
|
|
|
+ form_from_model(PowerOutlet, ['type', 'feed_leg', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class PowerOutletBulkEditForm(
|
|
|
|
|
+ form_from_model(PowerOutlet, ['type', 'feed_leg', 'power_port', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=PowerOutlet.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+ device = forms.ModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.all(),
|
|
|
|
|
+ required=False,
|
|
|
|
|
+ disabled=True,
|
|
|
|
|
+ widget=forms.HiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ nullable_fields = [
|
|
|
|
|
+ 'type', 'feed_leg', 'power_port', 'description',
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
|
|
+ super().__init__(*args, **kwargs)
|
|
|
|
|
+
|
|
|
|
|
+ # Limit power_port queryset to PowerPorts which belong to the parent Device
|
|
|
|
|
+ if 'device' in self.initial:
|
|
|
|
|
+ device = Device.objects.filter(pk=self.initial['device']).first()
|
|
|
|
|
+ self.fields['power_port'].queryset = PowerPort.objects.filter(device=device)
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.fields['power_port'].choices = ()
|
|
|
|
|
+ self.fields['power_port'].widget.attrs['disabled'] = True
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class PowerOutletBulkRenameForm(BulkRenameForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=PowerOutlet.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class PowerOutletBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=PowerOutlet.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class PowerOutletCSVForm(forms.ModelForm):
|
|
class PowerOutletCSVForm(forms.ModelForm):
|
|
|
device = FlexibleModelChoiceField(
|
|
device = FlexibleModelChoiceField(
|
|
|
queryset=Device.objects.all(),
|
|
queryset=Device.objects.all(),
|
|
@@ -2750,65 +2785,6 @@ class PowerOutletCSVForm(forms.ModelForm):
|
|
|
self.fields['power_port'].queryset = PowerPort.objects.none()
|
|
self.fields['power_port'].queryset = PowerPort.objects.none()
|
|
|
|
|
|
|
|
|
|
|
|
|
-class PowerOutletBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=PowerOutlet.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- device = forms.ModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- disabled=True,
|
|
|
|
|
- widget=forms.HiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(PowerOutletTypeChoices),
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
- feed_leg = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(PowerOutletFeedLegChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- )
|
|
|
|
|
- power_port = forms.ModelChoiceField(
|
|
|
|
|
- queryset=PowerPort.objects.all(),
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- nullable_fields = [
|
|
|
|
|
- 'type', 'feed_leg', 'power_port', 'description',
|
|
|
|
|
- ]
|
|
|
|
|
-
|
|
|
|
|
- def __init__(self, *args, **kwargs):
|
|
|
|
|
- super().__init__(*args, **kwargs)
|
|
|
|
|
-
|
|
|
|
|
- # Limit power_port queryset to PowerPorts which belong to the parent Device
|
|
|
|
|
- if 'device' in self.initial:
|
|
|
|
|
- device = Device.objects.filter(pk=self.initial['device']).first()
|
|
|
|
|
- self.fields['power_port'].queryset = PowerPort.objects.filter(device=device)
|
|
|
|
|
- else:
|
|
|
|
|
- self.fields['power_port'].choices = ()
|
|
|
|
|
- self.fields['power_port'].widget.attrs['disabled'] = True
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class PowerOutletBulkRenameForm(BulkRenameForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=PowerOutlet.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class PowerOutletBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=PowerOutlet.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
#
|
|
#
|
|
|
# Interfaces
|
|
# Interfaces
|
|
|
#
|
|
#
|
|
@@ -2985,6 +2961,102 @@ class InterfaceCreateForm(BootstrapMixin, InterfaceCommonForm, forms.Form):
|
|
|
self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+class InterfaceBulkCreateForm(
|
|
|
|
|
+ form_from_model(Interface, ['type', 'enabled', 'mtu', 'mgmt_only', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class InterfaceBulkEditForm(
|
|
|
|
|
+ form_from_model(Interface, ['type', 'enabled', 'lag', 'mac_address', 'mtu', 'mgmt_only', 'description', 'mode']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=Interface.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+ device = forms.ModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.all(),
|
|
|
|
|
+ required=False,
|
|
|
|
|
+ disabled=True,
|
|
|
|
|
+ widget=forms.HiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+ untagged_vlan = DynamicModelChoiceField(
|
|
|
|
|
+ queryset=VLAN.objects.all(),
|
|
|
|
|
+ required=False,
|
|
|
|
|
+ widget=APISelect(
|
|
|
|
|
+ display_field='display_name',
|
|
|
|
|
+ full=True,
|
|
|
|
|
+ additional_query_params={
|
|
|
|
|
+ 'site_id': 'null',
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ tagged_vlans = DynamicModelMultipleChoiceField(
|
|
|
|
|
+ queryset=VLAN.objects.all(),
|
|
|
|
|
+ required=False,
|
|
|
|
|
+ widget=APISelectMultiple(
|
|
|
|
|
+ display_field='display_name',
|
|
|
|
|
+ full=True,
|
|
|
|
|
+ additional_query_params={
|
|
|
|
|
+ 'site_id': 'null',
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ nullable_fields = [
|
|
|
|
|
+ 'lag', 'mac_address', 'mtu', 'description', 'mode', 'untagged_vlan', 'tagged_vlans'
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
|
|
+ super().__init__(*args, **kwargs)
|
|
|
|
|
+
|
|
|
|
|
+ # Limit LAG choices to interfaces which belong to the parent device (or VC master)
|
|
|
|
|
+ if 'device' in self.initial:
|
|
|
|
|
+ device = Device.objects.filter(pk=self.initial['device']).first()
|
|
|
|
|
+ self.fields['lag'].queryset = Interface.objects.filter(
|
|
|
|
|
+ device__in=[device, device.get_vc_master()],
|
|
|
|
|
+ type=InterfaceTypeChoices.TYPE_LAG
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ # Add current site to VLANs query params
|
|
|
|
|
+ self.fields['untagged_vlan'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
|
|
|
+ self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.fields['lag'].choices = ()
|
|
|
|
|
+ self.fields['lag'].widget.attrs['disabled'] = True
|
|
|
|
|
+
|
|
|
|
|
+ def clean(self):
|
|
|
|
|
+
|
|
|
|
|
+ # Untagged interfaces cannot be assigned tagged VLANs
|
|
|
|
|
+ if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and self.cleaned_data['tagged_vlans']:
|
|
|
|
|
+ raise forms.ValidationError({
|
|
|
|
|
+ 'mode': "An access interface cannot have tagged VLANs assigned."
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ # Remove all tagged VLAN assignments from "tagged all" interfaces
|
|
|
|
|
+ elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED_ALL:
|
|
|
|
|
+ self.cleaned_data['tagged_vlans'] = []
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class InterfaceBulkRenameForm(BulkRenameForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=Interface.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class InterfaceBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=Interface.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class InterfaceCSVForm(forms.ModelForm):
|
|
class InterfaceCSVForm(forms.ModelForm):
|
|
|
device = FlexibleModelChoiceField(
|
|
device = FlexibleModelChoiceField(
|
|
|
queryset=Device.objects.all(),
|
|
queryset=Device.objects.all(),
|
|
@@ -3052,129 +3124,6 @@ class InterfaceCSVForm(forms.ModelForm):
|
|
|
return self.cleaned_data['enabled']
|
|
return self.cleaned_data['enabled']
|
|
|
|
|
|
|
|
|
|
|
|
|
-class InterfaceBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=Interface.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- device = forms.ModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- disabled=True,
|
|
|
|
|
- widget=forms.HiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(InterfaceTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- enabled = forms.NullBooleanField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=BulkEditNullBooleanSelect()
|
|
|
|
|
- )
|
|
|
|
|
- lag = forms.ModelChoiceField(
|
|
|
|
|
- queryset=Interface.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- label='Parent LAG',
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- mac_address = forms.CharField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- label='MAC Address'
|
|
|
|
|
- )
|
|
|
|
|
- mtu = forms.IntegerField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- min_value=INTERFACE_MTU_MIN,
|
|
|
|
|
- max_value=INTERFACE_MTU_MAX,
|
|
|
|
|
- label='MTU'
|
|
|
|
|
- )
|
|
|
|
|
- mgmt_only = forms.NullBooleanField(
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=BulkEditNullBooleanSelect(),
|
|
|
|
|
- label='Management only'
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
- mode = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(InterfaceModeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- untagged_vlan = DynamicModelChoiceField(
|
|
|
|
|
- queryset=VLAN.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=APISelect(
|
|
|
|
|
- display_field='display_name',
|
|
|
|
|
- full=True,
|
|
|
|
|
- additional_query_params={
|
|
|
|
|
- 'site_id': 'null',
|
|
|
|
|
- },
|
|
|
|
|
- )
|
|
|
|
|
- )
|
|
|
|
|
- tagged_vlans = DynamicModelMultipleChoiceField(
|
|
|
|
|
- queryset=VLAN.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=APISelectMultiple(
|
|
|
|
|
- display_field='display_name',
|
|
|
|
|
- full=True,
|
|
|
|
|
- additional_query_params={
|
|
|
|
|
- 'site_id': 'null',
|
|
|
|
|
- },
|
|
|
|
|
- )
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- nullable_fields = [
|
|
|
|
|
- 'lag', 'mac_address', 'mtu', 'description', 'mode', 'untagged_vlan', 'tagged_vlans'
|
|
|
|
|
- ]
|
|
|
|
|
-
|
|
|
|
|
- def __init__(self, *args, **kwargs):
|
|
|
|
|
- super().__init__(*args, **kwargs)
|
|
|
|
|
-
|
|
|
|
|
- # Limit LAG choices to interfaces which belong to the parent device (or VC master)
|
|
|
|
|
- if 'device' in self.initial:
|
|
|
|
|
- device = Device.objects.filter(pk=self.initial['device']).first()
|
|
|
|
|
- self.fields['lag'].queryset = Interface.objects.filter(
|
|
|
|
|
- device__in=[device, device.get_vc_master()],
|
|
|
|
|
- type=InterfaceTypeChoices.TYPE_LAG
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- # Add current site to VLANs query params
|
|
|
|
|
- self.fields['untagged_vlan'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
|
|
|
- self.fields['tagged_vlans'].widget.add_additional_query_param('site_id', device.site.pk)
|
|
|
|
|
- else:
|
|
|
|
|
- self.fields['lag'].choices = ()
|
|
|
|
|
- self.fields['lag'].widget.attrs['disabled'] = True
|
|
|
|
|
-
|
|
|
|
|
- def clean(self):
|
|
|
|
|
-
|
|
|
|
|
- # Untagged interfaces cannot be assigned tagged VLANs
|
|
|
|
|
- if self.cleaned_data['mode'] == InterfaceModeChoices.MODE_ACCESS and self.cleaned_data['tagged_vlans']:
|
|
|
|
|
- raise forms.ValidationError({
|
|
|
|
|
- 'mode': "An access interface cannot have tagged VLANs assigned."
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- # Remove all tagged VLAN assignments from "tagged all" interfaces
|
|
|
|
|
- elif self.cleaned_data['mode'] == InterfaceModeChoices.MODE_TAGGED_ALL:
|
|
|
|
|
- self.cleaned_data['tagged_vlans'] = []
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class InterfaceBulkRenameForm(BulkRenameForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=Interface.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class InterfaceBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=Interface.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
#
|
|
#
|
|
|
# Front pass-through ports
|
|
# Front pass-through ports
|
|
|
#
|
|
#
|
|
@@ -3283,6 +3232,44 @@ class FrontPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+# class FrontPortBulkCreateForm(
|
|
|
|
|
+# form_from_model(FrontPort, ['type', 'description', 'tags']),
|
|
|
|
|
+# DeviceBulkAddComponentForm
|
|
|
|
|
+# ):
|
|
|
|
|
+# pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class FrontPortBulkEditForm(
|
|
|
|
|
+ form_from_model(FrontPort, ['type', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=FrontPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ nullable_fields = [
|
|
|
|
|
+ 'description',
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class FrontPortBulkRenameForm(BulkRenameForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=FrontPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class FrontPortBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=FrontPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class FrontPortCSVForm(forms.ModelForm):
|
|
class FrontPortCSVForm(forms.ModelForm):
|
|
|
device = FlexibleModelChoiceField(
|
|
device = FlexibleModelChoiceField(
|
|
|
queryset=Device.objects.all(),
|
|
queryset=Device.objects.all(),
|
|
@@ -3331,41 +3318,6 @@ class FrontPortCSVForm(forms.ModelForm):
|
|
|
self.fields['rear_port'].queryset = RearPort.objects.none()
|
|
self.fields['rear_port'].queryset = RearPort.objects.none()
|
|
|
|
|
|
|
|
|
|
|
|
|
-class FrontPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=FrontPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(PortTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- nullable_fields = [
|
|
|
|
|
- 'description',
|
|
|
|
|
- ]
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class FrontPortBulkRenameForm(BulkRenameForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=FrontPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class FrontPortBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=FrontPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
#
|
|
#
|
|
|
# Rear pass-through ports
|
|
# Rear pass-through ports
|
|
|
#
|
|
#
|
|
@@ -3418,6 +3370,44 @@ class RearPortCreateForm(BootstrapMixin, forms.Form):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+class RearPortBulkCreateForm(
|
|
|
|
|
+ form_from_model(RearPort, ['type', 'positions', 'description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class RearPortBulkEditForm(
|
|
|
|
|
+ form_from_model(RearPort, ['type', 'description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=RearPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ nullable_fields = [
|
|
|
|
|
+ 'description',
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class RearPortBulkRenameForm(BulkRenameForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=RearPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class RearPortBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=RearPort.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
class RearPortCSVForm(forms.ModelForm):
|
|
class RearPortCSVForm(forms.ModelForm):
|
|
|
device = FlexibleModelChoiceField(
|
|
device = FlexibleModelChoiceField(
|
|
|
queryset=Device.objects.all(),
|
|
queryset=Device.objects.all(),
|
|
@@ -3436,40 +3426,145 @@ class RearPortCSVForm(forms.ModelForm):
|
|
|
fields = RearPort.csv_headers
|
|
fields = RearPort.csv_headers
|
|
|
|
|
|
|
|
|
|
|
|
|
-class RearPortBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=RearPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
|
|
+#
|
|
|
|
|
+# Device bays
|
|
|
|
|
+#
|
|
|
|
|
+
|
|
|
|
|
+class DeviceBayFilterForm(DeviceComponentFilterForm):
|
|
|
|
|
+ model = DeviceBay
|
|
|
|
|
+ tag = TagFilterField(model)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class DeviceBayForm(BootstrapMixin, forms.ModelForm):
|
|
|
|
|
+ tags = TagField(
|
|
|
|
|
+ required=False
|
|
|
)
|
|
)
|
|
|
- type = forms.ChoiceField(
|
|
|
|
|
- choices=add_blank_choice(PortTypeChoices),
|
|
|
|
|
- required=False,
|
|
|
|
|
- widget=StaticSelect2()
|
|
|
|
|
|
|
+
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = DeviceBay
|
|
|
|
|
+ fields = [
|
|
|
|
|
+ 'device', 'name', 'description', 'tags',
|
|
|
|
|
+ ]
|
|
|
|
|
+ widgets = {
|
|
|
|
|
+ 'device': forms.HiddenInput(),
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class DeviceBayCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
+ device = DynamicModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.prefetch_related('device_type__manufacturer')
|
|
|
)
|
|
)
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
|
|
+ name_pattern = ExpandableNameField(
|
|
|
|
|
+ label='Name'
|
|
|
|
|
+ )
|
|
|
|
|
+ tags = TagField(
|
|
|
required=False
|
|
required=False
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
|
|
|
|
|
+ installed_device = forms.ModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.all(),
|
|
|
|
|
+ label='Child Device',
|
|
|
|
|
+ help_text="Child devices must first be created and assigned to the site/rack of the parent device.",
|
|
|
|
|
+ widget=StaticSelect2(),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, device_bay, *args, **kwargs):
|
|
|
|
|
+
|
|
|
|
|
+ super().__init__(*args, **kwargs)
|
|
|
|
|
+
|
|
|
|
|
+ self.fields['installed_device'].queryset = Device.objects.filter(
|
|
|
|
|
+ site=device_bay.device.site,
|
|
|
|
|
+ rack=device_bay.device.rack,
|
|
|
|
|
+ parent_bay__isnull=True,
|
|
|
|
|
+ device_type__u_height=0,
|
|
|
|
|
+ device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
|
|
|
|
|
+ ).exclude(pk=device_bay.device.pk)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class DeviceBayBulkCreateForm(
|
|
|
|
|
+ form_from_model(DeviceBay, ['description', 'tags']),
|
|
|
|
|
+ DeviceBulkAddComponentForm
|
|
|
|
|
+):
|
|
|
|
|
+ tags = TagField(
|
|
|
|
|
+ required=False
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class DeviceBayBulkEditForm(
|
|
|
|
|
+ form_from_model(DeviceBay, ['description']),
|
|
|
|
|
+ BootstrapMixin,
|
|
|
|
|
+ AddRemoveTagsForm,
|
|
|
|
|
+ BulkEditForm
|
|
|
|
|
+):
|
|
|
|
|
+ pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
+ queryset=DeviceBay.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
class Meta:
|
|
class Meta:
|
|
|
- nullable_fields = [
|
|
|
|
|
|
|
+ nullable_fields = (
|
|
|
'description',
|
|
'description',
|
|
|
- ]
|
|
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
|
|
|
|
|
-class RearPortBulkRenameForm(BulkRenameForm):
|
|
|
|
|
|
|
+class DeviceBayBulkRenameForm(BulkRenameForm):
|
|
|
pk = forms.ModelMultipleChoiceField(
|
|
pk = forms.ModelMultipleChoiceField(
|
|
|
- queryset=RearPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
|
|
+ queryset=DeviceBay.objects.all(),
|
|
|
|
|
+ widget=forms.MultipleHiddenInput()
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-class RearPortBulkDisconnectForm(ConfirmationForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=RearPort.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput
|
|
|
|
|
|
|
+class DeviceBayCSVForm(forms.ModelForm):
|
|
|
|
|
+ device = FlexibleModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.all(),
|
|
|
|
|
+ to_field_name='name',
|
|
|
|
|
+ help_text='Name or ID of device',
|
|
|
|
|
+ error_messages={
|
|
|
|
|
+ 'invalid_choice': 'Device not found.',
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ installed_device = FlexibleModelChoiceField(
|
|
|
|
|
+ queryset=Device.objects.all(),
|
|
|
|
|
+ required=False,
|
|
|
|
|
+ to_field_name='name',
|
|
|
|
|
+ help_text='Name or ID of device',
|
|
|
|
|
+ error_messages={
|
|
|
|
|
+ 'invalid_choice': 'Child device not found.',
|
|
|
|
|
+ }
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ class Meta:
|
|
|
|
|
+ model = DeviceBay
|
|
|
|
|
+ fields = DeviceBay.csv_headers
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, *args, **kwargs):
|
|
|
|
|
+ super().__init__(*args, **kwargs)
|
|
|
|
|
+
|
|
|
|
|
+ # Limit installed device choices to devices of the correct type and location
|
|
|
|
|
+ if self.is_bound:
|
|
|
|
|
+ try:
|
|
|
|
|
+ device = self.fields['device'].to_python(self.data['device'])
|
|
|
|
|
+ except forms.ValidationError:
|
|
|
|
|
+ device = None
|
|
|
|
|
+ else:
|
|
|
|
|
+ try:
|
|
|
|
|
+ device = self.instance.device
|
|
|
|
|
+ except Device.DoesNotExist:
|
|
|
|
|
+ device = None
|
|
|
|
|
+
|
|
|
|
|
+ if device:
|
|
|
|
|
+ self.fields['installed_device'].queryset = Device.objects.filter(
|
|
|
|
|
+ site=device.site,
|
|
|
|
|
+ rack=device.rack,
|
|
|
|
|
+ parent_bay__isnull=True,
|
|
|
|
|
+ device_type__u_height=0,
|
|
|
|
|
+ device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
|
|
|
|
|
+ ).exclude(pk=device.pk)
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.fields['installed_device'].queryset = Interface.objects.none()
|
|
|
|
|
+
|
|
|
|
|
|
|
|
#
|
|
#
|
|
|
# Cables
|
|
# Cables
|
|
@@ -3954,136 +4049,6 @@ class CableFilterForm(BootstrapMixin, forms.Form):
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-#
|
|
|
|
|
-# Device bays
|
|
|
|
|
-#
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayFilterForm(DeviceComponentFilterForm):
|
|
|
|
|
- model = DeviceBay
|
|
|
|
|
- tag = TagFilterField(model)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayForm(BootstrapMixin, forms.ModelForm):
|
|
|
|
|
- tags = TagField(
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- model = DeviceBay
|
|
|
|
|
- fields = [
|
|
|
|
|
- 'device', 'name', 'description', 'tags',
|
|
|
|
|
- ]
|
|
|
|
|
- widgets = {
|
|
|
|
|
- 'device': forms.HiddenInput(),
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayCreateForm(BootstrapMixin, forms.Form):
|
|
|
|
|
- device = DynamicModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.prefetch_related('device_type__manufacturer')
|
|
|
|
|
- )
|
|
|
|
|
- name_pattern = ExpandableNameField(
|
|
|
|
|
- label='Name'
|
|
|
|
|
- )
|
|
|
|
|
- tags = TagField(
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
|
|
|
|
|
- installed_device = forms.ModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.all(),
|
|
|
|
|
- label='Child Device',
|
|
|
|
|
- help_text="Child devices must first be created and assigned to the site/rack of the parent device.",
|
|
|
|
|
- widget=StaticSelect2(),
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- def __init__(self, device_bay, *args, **kwargs):
|
|
|
|
|
-
|
|
|
|
|
- super().__init__(*args, **kwargs)
|
|
|
|
|
-
|
|
|
|
|
- self.fields['installed_device'].queryset = Device.objects.filter(
|
|
|
|
|
- site=device_bay.device.site,
|
|
|
|
|
- rack=device_bay.device.rack,
|
|
|
|
|
- parent_bay__isnull=True,
|
|
|
|
|
- device_type__u_height=0,
|
|
|
|
|
- device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
|
|
|
|
|
- ).exclude(pk=device_bay.device.pk)
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayBulkEditForm(BootstrapMixin, AddRemoveTagsForm, BulkEditForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=DeviceBay.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
- description = forms.CharField(
|
|
|
|
|
- max_length=100,
|
|
|
|
|
- required=False
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- nullable_fields = (
|
|
|
|
|
- 'description',
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayCSVForm(forms.ModelForm):
|
|
|
|
|
- device = FlexibleModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.all(),
|
|
|
|
|
- to_field_name='name',
|
|
|
|
|
- help_text='Name or ID of device',
|
|
|
|
|
- error_messages={
|
|
|
|
|
- 'invalid_choice': 'Device not found.',
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- installed_device = FlexibleModelChoiceField(
|
|
|
|
|
- queryset=Device.objects.all(),
|
|
|
|
|
- required=False,
|
|
|
|
|
- to_field_name='name',
|
|
|
|
|
- help_text='Name or ID of device',
|
|
|
|
|
- error_messages={
|
|
|
|
|
- 'invalid_choice': 'Child device not found.',
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
- class Meta:
|
|
|
|
|
- model = DeviceBay
|
|
|
|
|
- fields = DeviceBay.csv_headers
|
|
|
|
|
-
|
|
|
|
|
- def __init__(self, *args, **kwargs):
|
|
|
|
|
- super().__init__(*args, **kwargs)
|
|
|
|
|
-
|
|
|
|
|
- # Limit installed device choices to devices of the correct type and location
|
|
|
|
|
- if self.is_bound:
|
|
|
|
|
- try:
|
|
|
|
|
- device = self.fields['device'].to_python(self.data['device'])
|
|
|
|
|
- except forms.ValidationError:
|
|
|
|
|
- device = None
|
|
|
|
|
- else:
|
|
|
|
|
- try:
|
|
|
|
|
- device = self.instance.device
|
|
|
|
|
- except Device.DoesNotExist:
|
|
|
|
|
- device = None
|
|
|
|
|
-
|
|
|
|
|
- if device:
|
|
|
|
|
- self.fields['installed_device'].queryset = Device.objects.filter(
|
|
|
|
|
- site=device.site,
|
|
|
|
|
- rack=device.rack,
|
|
|
|
|
- parent_bay__isnull=True,
|
|
|
|
|
- device_type__u_height=0,
|
|
|
|
|
- device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
|
|
|
|
|
- ).exclude(pk=device.pk)
|
|
|
|
|
- else:
|
|
|
|
|
- self.fields['installed_device'].queryset = Interface.objects.none()
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-class DeviceBayBulkRenameForm(BulkRenameForm):
|
|
|
|
|
- pk = forms.ModelMultipleChoiceField(
|
|
|
|
|
- queryset=DeviceBay.objects.all(),
|
|
|
|
|
- widget=forms.MultipleHiddenInput()
|
|
|
|
|
- )
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
#
|
|
#
|
|
|
# Connections
|
|
# Connections
|
|
|
#
|
|
#
|