mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Formatting cleanup
This commit is contained in:
@ -21,14 +21,22 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
|
|||||||
class ProviderForm(BootstrapMixin, CustomFieldForm):
|
class ProviderForm(BootstrapMixin, CustomFieldForm):
|
||||||
slug = SlugField()
|
slug = SlugField()
|
||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Provider
|
model = Provider
|
||||||
fields = ['name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments', 'tags']
|
fields = [
|
||||||
|
'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments', 'tags',
|
||||||
|
]
|
||||||
widgets = {
|
widgets = {
|
||||||
'noc_contact': SmallTextarea(attrs={'rows': 5}),
|
'noc_contact': SmallTextarea(
|
||||||
'admin_contact': SmallTextarea(attrs={'rows': 5}),
|
attrs={'rows': 5}
|
||||||
|
),
|
||||||
|
'admin_contact': SmallTextarea(
|
||||||
|
attrs={'rows': 5}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'name': "Full name of the provider",
|
'name': "Full name of the provider",
|
||||||
@ -54,23 +62,57 @@ class ProviderCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class ProviderBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class ProviderBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Provider.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
asn = forms.IntegerField(required=False, label='ASN')
|
queryset=Provider.objects.all(),
|
||||||
account = forms.CharField(max_length=30, required=False, label='Account number')
|
widget=forms.MultipleHiddenInput
|
||||||
portal_url = forms.URLField(required=False, label='Portal')
|
)
|
||||||
noc_contact = forms.CharField(required=False, widget=SmallTextarea, label='NOC contact')
|
asn = forms.IntegerField(
|
||||||
admin_contact = forms.CharField(required=False, widget=SmallTextarea, label='Admin contact')
|
required=False,
|
||||||
comments = CommentField(widget=SmallTextarea)
|
label='ASN'
|
||||||
|
)
|
||||||
|
account = forms.CharField(
|
||||||
|
max_length=30,
|
||||||
|
required=False,
|
||||||
|
label='Account number'
|
||||||
|
)
|
||||||
|
portal_url = forms.URLField(
|
||||||
|
required=False,
|
||||||
|
label='Portal'
|
||||||
|
)
|
||||||
|
noc_contact = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
widget=SmallTextarea,
|
||||||
|
label='NOC contact'
|
||||||
|
)
|
||||||
|
admin_contact = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
widget=SmallTextarea,
|
||||||
|
label='Admin contact'
|
||||||
|
)
|
||||||
|
comments = CommentField(
|
||||||
|
widget=SmallTextarea()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments']
|
nullable_fields = [
|
||||||
|
'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class ProviderFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Provider
|
model = Provider
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
site = FilterChoiceField(queryset=Site.objects.all(), to_field_name='slug')
|
required=False,
|
||||||
asn = forms.IntegerField(required=False, label='ASN')
|
label='Search'
|
||||||
|
)
|
||||||
|
site = FilterChoiceField(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
to_field_name='slug'
|
||||||
|
)
|
||||||
|
asn = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='ASN'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -82,7 +124,9 @@ class CircuitTypeForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CircuitType
|
model = CircuitType
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class CircuitTypeCSVForm(forms.ModelForm):
|
class CircuitTypeCSVForm(forms.ModelForm):
|
||||||
@ -102,7 +146,9 @@ class CircuitTypeCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
class CircuitForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Circuit
|
model = Circuit
|
||||||
@ -157,28 +203,61 @@ class CircuitCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class CircuitBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Circuit.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
type = forms.ModelChoiceField(queryset=CircuitType.objects.all(), required=False)
|
queryset=Circuit.objects.all(),
|
||||||
provider = forms.ModelChoiceField(queryset=Provider.objects.all(), required=False)
|
widget=forms.MultipleHiddenInput
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(CIRCUIT_STATUS_CHOICES), required=False, initial='')
|
)
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
type = forms.ModelChoiceField(
|
||||||
commit_rate = forms.IntegerField(required=False, label='Commit rate (Kbps)')
|
queryset=CircuitType.objects.all(),
|
||||||
description = forms.CharField(max_length=100, required=False)
|
required=False
|
||||||
comments = CommentField(widget=SmallTextarea)
|
)
|
||||||
|
provider = forms.ModelChoiceField(
|
||||||
|
queryset=Provider.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
status = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(CIRCUIT_STATUS_CHOICES),
|
||||||
|
required=False,
|
||||||
|
initial=''
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
commit_rate = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='Commit rate (Kbps)'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
comments = CommentField(
|
||||||
|
widget=SmallTextarea
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['tenant', 'commit_rate', 'description', 'comments']
|
nullable_fields = [
|
||||||
|
'tenant', 'commit_rate', 'description', 'comments',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Circuit
|
model = Circuit
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
type = FilterChoiceField(
|
type = FilterChoiceField(
|
||||||
queryset=CircuitType.objects.annotate(filter_count=Count('circuits')),
|
queryset=CircuitType.objects.annotate(
|
||||||
|
filter_count=Count('circuits')
|
||||||
|
),
|
||||||
to_field_name='slug'
|
to_field_name='slug'
|
||||||
)
|
)
|
||||||
provider = FilterChoiceField(
|
provider = FilterChoiceField(
|
||||||
queryset=Provider.objects.annotate(filter_count=Count('circuits')),
|
queryset=Provider.objects.annotate(
|
||||||
|
filter_count=Count('circuits')
|
||||||
|
),
|
||||||
to_field_name='slug'
|
to_field_name='slug'
|
||||||
)
|
)
|
||||||
status = AnnotatedMultipleChoiceField(
|
status = AnnotatedMultipleChoiceField(
|
||||||
@ -188,15 +267,23 @@ class CircuitFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('circuits')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('circuits')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('circuit_terminations')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('circuit_terminations')
|
||||||
|
),
|
||||||
to_field_name='slug'
|
to_field_name='slug'
|
||||||
)
|
)
|
||||||
commit_rate = forms.IntegerField(required=False, min_value=0, label='Commit rate (Kbps)')
|
commit_rate = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
min_value=0,
|
||||||
|
label='Commit rate (Kbps)'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -193,7 +193,9 @@ class TagForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Tag
|
model = Tag
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class AddRemoveTagsForm(forms.Form):
|
class AddRemoveTagsForm(forms.Form):
|
||||||
@ -208,7 +210,10 @@ class AddRemoveTagsForm(forms.Form):
|
|||||||
|
|
||||||
class TagFilterForm(BootstrapMixin, forms.Form):
|
class TagFilterForm(BootstrapMixin, forms.Form):
|
||||||
model = Tag
|
model = Tag
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -249,7 +254,9 @@ class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['description']
|
nullable_fields = [
|
||||||
|
'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ConfigContextFilterForm(BootstrapMixin, forms.Form):
|
class ConfigContextFilterForm(BootstrapMixin, forms.Form):
|
||||||
@ -291,7 +298,9 @@ class ImageAttachmentForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ImageAttachment
|
model = ImageAttachment
|
||||||
fields = ['name', 'image']
|
fields = [
|
||||||
|
'name', 'image',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -34,11 +34,15 @@ IPADDRESS_MASK_LENGTH_CHOICES = add_blank_choice([(i, i) for i in range(1, 129)]
|
|||||||
#
|
#
|
||||||
|
|
||||||
class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
class VRFForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VRF
|
model = VRF
|
||||||
fields = ['name', 'rd', 'enforce_unique', 'description', 'tenant_group', 'tenant', 'tags']
|
fields = [
|
||||||
|
'name', 'rd', 'enforce_unique', 'description', 'tenant_group', 'tenant', 'tags',
|
||||||
|
]
|
||||||
labels = {
|
labels = {
|
||||||
'rd': "RD",
|
'rd': "RD",
|
||||||
}
|
}
|
||||||
@ -67,22 +71,40 @@ class VRFCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class VRFBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
queryset=VRF.objects.all(),
|
||||||
enforce_unique = forms.NullBooleanField(
|
widget=forms.MultipleHiddenInput()
|
||||||
required=False, widget=BulkEditNullBooleanSelect, label='Enforce unique space'
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
enforce_unique = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect(),
|
||||||
|
label='Enforce unique space'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
)
|
)
|
||||||
description = forms.CharField(max_length=100, required=False)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['tenant', 'description']
|
nullable_fields = [
|
||||||
|
'tenant', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class VRFFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class VRFFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = VRF
|
model = VRF
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('vrfs')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('vrfs')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -97,7 +119,9 @@ class RIRForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RIR
|
model = RIR
|
||||||
fields = ['name', 'slug', 'is_private']
|
fields = [
|
||||||
|
'name', 'slug', 'is_private',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class RIRCSVForm(forms.ModelForm):
|
class RIRCSVForm(forms.ModelForm):
|
||||||
@ -112,11 +136,17 @@ class RIRCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class RIRFilterForm(BootstrapMixin, forms.Form):
|
class RIRFilterForm(BootstrapMixin, forms.Form):
|
||||||
is_private = forms.NullBooleanField(required=False, label='Private', widget=forms.Select(choices=[
|
is_private = forms.NullBooleanField(
|
||||||
('', '---------'),
|
required=False,
|
||||||
('True', 'Yes'),
|
label='Private',
|
||||||
('False', 'No'),
|
widget=forms.Select(
|
||||||
]))
|
choices=[
|
||||||
|
('', '---------'),
|
||||||
|
('True', 'Yes'),
|
||||||
|
('False', 'No'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -124,11 +154,15 @@ class RIRFilterForm(BootstrapMixin, forms.Form):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class AggregateForm(BootstrapMixin, CustomFieldForm):
|
class AggregateForm(BootstrapMixin, CustomFieldForm):
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Aggregate
|
model = Aggregate
|
||||||
fields = ['prefix', 'rir', 'date_added', 'description', 'tags']
|
fields = [
|
||||||
|
'prefix', 'rir', 'date_added', 'description', 'tags',
|
||||||
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'prefix': "IPv4 or IPv6 network",
|
'prefix': "IPv4 or IPv6 network",
|
||||||
'rir': "Regional Internet Registry responsible for this prefix",
|
'rir': "Regional Internet Registry responsible for this prefix",
|
||||||
@ -152,19 +186,40 @@ class AggregateCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class AggregateBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Aggregate.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
rir = forms.ModelChoiceField(queryset=RIR.objects.all(), required=False, label='RIR')
|
queryset=Aggregate.objects.all(),
|
||||||
date_added = forms.DateField(required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
description = forms.CharField(max_length=100, required=False)
|
)
|
||||||
|
rir = forms.ModelChoiceField(
|
||||||
|
queryset=RIR.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label='RIR'
|
||||||
|
)
|
||||||
|
date_added = forms.DateField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['date_added', 'description']
|
nullable_fields = [
|
||||||
|
'date_added', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class AggregateFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Aggregate
|
model = Aggregate
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address Family')
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
|
family = forms.ChoiceField(
|
||||||
|
required=False,
|
||||||
|
choices=IP_FAMILY_CHOICES,
|
||||||
|
label='Address family'
|
||||||
|
)
|
||||||
rir = FilterChoiceField(
|
rir = FilterChoiceField(
|
||||||
queryset=RIR.objects.annotate(filter_count=Count('aggregates')),
|
queryset=RIR.objects.annotate(filter_count=Count('aggregates')),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -181,7 +236,9 @@ class RoleForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Role
|
model = Role
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class RoleCSVForm(forms.ModelForm):
|
class RoleCSVForm(forms.ModelForm):
|
||||||
@ -205,7 +262,10 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='Site',
|
label='Site',
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'vlan_group', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'vlan_group',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
vlan_group = ChainedModelChoiceField(
|
vlan_group = ChainedModelChoiceField(
|
||||||
@ -217,7 +277,10 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
label='VLAN group',
|
label='VLAN group',
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/ipam/vlan-groups/?site_id={{site}}',
|
api_url='/api/ipam/vlan-groups/?site_id={{site}}',
|
||||||
attrs={'filter-for': 'vlan', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'vlan',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
vlan = ChainedModelChoiceField(
|
vlan = ChainedModelChoiceField(
|
||||||
@ -229,7 +292,8 @@ class PrefixForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
required=False,
|
required=False,
|
||||||
label='VLAN',
|
label='VLAN',
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/ipam/vlans/?site_id={{site}}&group_id={{vlan_group}}', display_field='display_name'
|
api_url='/api/ipam/vlans/?site_id={{site}}&group_id={{vlan_group}}',
|
||||||
|
display_field='display_name'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
tags = TagField(required=False)
|
tags = TagField(required=False)
|
||||||
@ -345,35 +409,84 @@ class PrefixCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class PrefixBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Prefix.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
|
queryset=Prefix.objects.all(),
|
||||||
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
|
widget=forms.MultipleHiddenInput()
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
)
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(PREFIX_STATUS_CHOICES), required=False)
|
site = forms.ModelChoiceField(
|
||||||
role = forms.ModelChoiceField(queryset=Role.objects.all(), required=False)
|
queryset=Site.objects.all(),
|
||||||
is_pool = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label='Is a pool')
|
required=False
|
||||||
description = forms.CharField(max_length=100, required=False)
|
)
|
||||||
|
vrf = forms.ModelChoiceField(
|
||||||
|
queryset=VRF.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label='VRF'
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
status = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(PREFIX_STATUS_CHOICES),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
role = forms.ModelChoiceField(
|
||||||
|
queryset=Role.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
is_pool = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect(),
|
||||||
|
label='Is a pool'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['site', 'vrf', 'tenant', 'role', 'description']
|
nullable_fields = [
|
||||||
|
'site', 'vrf', 'tenant', 'role', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Prefix
|
model = Prefix
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
within_include = forms.CharField(required=False, label='Search within', widget=forms.TextInput(attrs={
|
required=False,
|
||||||
'placeholder': 'Prefix',
|
label='Search'
|
||||||
}))
|
)
|
||||||
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address family')
|
within_include = forms.CharField(
|
||||||
mask_length = forms.ChoiceField(required=False, choices=PREFIX_MASK_LENGTH_CHOICES, label='Mask length')
|
required=False,
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
'placeholder': 'Prefix',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
label='Search within'
|
||||||
|
)
|
||||||
|
family = forms.ChoiceField(
|
||||||
|
required=False,
|
||||||
|
choices=IP_FAMILY_CHOICES,
|
||||||
|
label='Address family'
|
||||||
|
)
|
||||||
|
mask_length = forms.ChoiceField(
|
||||||
|
required=False,
|
||||||
|
choices=PREFIX_MASK_LENGTH_CHOICES,
|
||||||
|
label='Mask length'
|
||||||
|
)
|
||||||
vrf = FilterChoiceField(
|
vrf = FilterChoiceField(
|
||||||
queryset=VRF.objects.annotate(filter_count=Count('prefixes')),
|
queryset=VRF.objects.annotate(
|
||||||
|
filter_count=Count('prefixes')
|
||||||
|
),
|
||||||
to_field_name='rd',
|
to_field_name='rd',
|
||||||
label='VRF',
|
label='VRF',
|
||||||
null_label='-- Global --'
|
null_label='-- Global --'
|
||||||
)
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('prefixes')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('prefixes')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -384,16 +497,23 @@ class PrefixFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('prefixes')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('prefixes')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
role = FilterChoiceField(
|
role = FilterChoiceField(
|
||||||
queryset=Role.objects.annotate(filter_count=Count('prefixes')),
|
queryset=Role.objects.annotate(
|
||||||
|
filter_count=Count('prefixes')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
expand = forms.BooleanField(required=False, label='Expand prefix hierarchy')
|
expand = forms.BooleanField(
|
||||||
|
required=False,
|
||||||
|
label='Expand prefix hierarchy'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -410,7 +530,9 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
required=False,
|
required=False,
|
||||||
label='Site',
|
label='Site',
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'nat_rack'}
|
attrs={
|
||||||
|
'filter-for': 'nat_rack'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
nat_rack = ChainedModelChoiceField(
|
nat_rack = ChainedModelChoiceField(
|
||||||
@ -423,7 +545,10 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/dcim/racks/?site_id={{nat_site}}',
|
api_url='/api/dcim/racks/?site_id={{nat_site}}',
|
||||||
display_field='display_name',
|
display_field='display_name',
|
||||||
attrs={'filter-for': 'nat_device', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'nat_device',
|
||||||
|
'nullable': 'true'
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
nat_device = ChainedModelChoiceField(
|
nat_device = ChainedModelChoiceField(
|
||||||
@ -462,8 +587,13 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
obj_label='address'
|
obj_label='address'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
primary_for_parent = forms.BooleanField(required=False, label='Make this the primary IP for the device/VM')
|
primary_for_parent = forms.BooleanField(
|
||||||
tags = TagField(required=False)
|
required=False,
|
||||||
|
label='Make this the primary IP for the device/VM'
|
||||||
|
)
|
||||||
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
@ -538,14 +668,18 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
|
|
||||||
|
|
||||||
class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
|
class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
|
||||||
pattern = ExpandableIPAddressField(label='Address pattern')
|
pattern = ExpandableIPAddressField(
|
||||||
|
label='Address pattern'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
class IPAddressBulkAddForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
fields = ['address', 'vrf', 'status', 'role', 'description', 'tenant_group', 'tenant']
|
fields = [
|
||||||
|
'address', 'vrf', 'status', 'role', 'description', 'tenant_group', 'tenant',
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
@ -612,7 +746,6 @@ class IPAddressCSVForm(forms.ModelForm):
|
|||||||
fields = IPAddress.csv_headers
|
fields = IPAddress.csv_headers
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
device = self.cleaned_data.get('device')
|
device = self.cleaned_data.get('device')
|
||||||
@ -677,38 +810,86 @@ class IPAddressCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class IPAddressBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=IPAddress.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF')
|
queryset=IPAddress.objects.all(),
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(IPADDRESS_STATUS_CHOICES), required=False)
|
)
|
||||||
role = forms.ChoiceField(choices=add_blank_choice(IPADDRESS_ROLE_CHOICES), required=False)
|
vrf = forms.ModelChoiceField(
|
||||||
description = forms.CharField(max_length=100, required=False)
|
queryset=VRF.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label='VRF'
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
status = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(IPADDRESS_STATUS_CHOICES),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
role = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(IPADDRESS_ROLE_CHOICES),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100, required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['vrf', 'role', 'tenant', 'description']
|
nullable_fields = [
|
||||||
|
'vrf', 'role', 'tenant', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class IPAddressAssignForm(BootstrapMixin, forms.Form):
|
class IPAddressAssignForm(BootstrapMixin, forms.Form):
|
||||||
vrf = forms.ModelChoiceField(queryset=VRF.objects.all(), required=False, label='VRF', empty_label='Global')
|
vrf = forms.ModelChoiceField(
|
||||||
address = forms.CharField(label='IP Address')
|
queryset=VRF.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label='VRF',
|
||||||
|
empty_label='Global'
|
||||||
|
)
|
||||||
|
address = forms.CharField(
|
||||||
|
label='IP Address'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = IPAddress
|
model = IPAddress
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
parent = forms.CharField(required=False, label='Parent Prefix', widget=forms.TextInput(attrs={
|
required=False,
|
||||||
'placeholder': 'Prefix',
|
label='Search'
|
||||||
}))
|
)
|
||||||
family = forms.ChoiceField(required=False, choices=IP_FAMILY_CHOICES, label='Address family')
|
parent = forms.CharField(
|
||||||
mask_length = forms.ChoiceField(required=False, choices=IPADDRESS_MASK_LENGTH_CHOICES, label='Mask length')
|
required=False,
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
'placeholder': 'Prefix',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
label='Parent Prefix'
|
||||||
|
)
|
||||||
|
family = forms.ChoiceField(
|
||||||
|
required=False,
|
||||||
|
choices=IP_FAMILY_CHOICES,
|
||||||
|
label='Address family'
|
||||||
|
)
|
||||||
|
mask_length = forms.ChoiceField(
|
||||||
|
required=False,
|
||||||
|
choices=IPADDRESS_MASK_LENGTH_CHOICES,
|
||||||
|
label='Mask length'
|
||||||
|
)
|
||||||
vrf = FilterChoiceField(
|
vrf = FilterChoiceField(
|
||||||
queryset=VRF.objects.annotate(filter_count=Count('ip_addresses')),
|
queryset=VRF.objects.annotate(
|
||||||
|
filter_count=Count('ip_addresses')
|
||||||
|
),
|
||||||
to_field_name='rd',
|
to_field_name='rd',
|
||||||
label='VRF',
|
label='VRF',
|
||||||
null_label='-- Global --'
|
null_label='-- Global --'
|
||||||
)
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('ip_addresses')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('ip_addresses')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -735,7 +916,9 @@ class VLANGroupForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLANGroup
|
model = VLANGroup
|
||||||
fields = ['site', 'name', 'slug']
|
fields = [
|
||||||
|
'site', 'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class VLANGroupCSVForm(forms.ModelForm):
|
class VLANGroupCSVForm(forms.ModelForm):
|
||||||
@ -760,7 +943,9 @@ class VLANGroupCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
class VLANGroupFilterForm(BootstrapMixin, forms.Form):
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('vlan_groups')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('vlan_groups')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- Global --'
|
null_label='-- Global --'
|
||||||
)
|
)
|
||||||
@ -775,7 +960,10 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
queryset=Site.objects.all(),
|
queryset=Site.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'group', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'group',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
group = ChainedModelChoiceField(
|
group = ChainedModelChoiceField(
|
||||||
@ -793,7 +981,9 @@ class VLANForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLAN
|
model = VLAN
|
||||||
fields = ['site', 'group', 'vid', 'name', 'status', 'role', 'description', 'tenant_group', 'tenant', 'tags']
|
fields = [
|
||||||
|
'site', 'group', 'vid', 'name', 'status', 'role', 'description', 'tenant_group', 'tenant', 'tags',
|
||||||
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'site': "Leave blank if this VLAN spans multiple sites",
|
'site': "Leave blank if this VLAN spans multiple sites",
|
||||||
'group': "VLAN group (optional)",
|
'group': "VLAN group (optional)",
|
||||||
@ -850,7 +1040,6 @@ class VLANCSVForm(forms.ModelForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
site = self.cleaned_data.get('site')
|
site = self.cleaned_data.get('site')
|
||||||
@ -862,39 +1051,75 @@ class VLANCSVForm(forms.ModelForm):
|
|||||||
self.instance.group = VLANGroup.objects.get(site=site, name=group_name)
|
self.instance.group = VLANGroup.objects.get(site=site, name=group_name)
|
||||||
except VLANGroup.DoesNotExist:
|
except VLANGroup.DoesNotExist:
|
||||||
if site:
|
if site:
|
||||||
raise forms.ValidationError("VLAN group {} not found for site {}".format(group_name, site))
|
raise forms.ValidationError(
|
||||||
|
"VLAN group {} not found for site {}".format(group_name, site)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise forms.ValidationError("Global VLAN group {} not found".format(group_name))
|
raise forms.ValidationError(
|
||||||
|
"Global VLAN group {} not found".format(group_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class VLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=VLAN.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
|
queryset=VLAN.objects.all(),
|
||||||
group = forms.ModelChoiceField(queryset=VLANGroup.objects.all(), required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
)
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(VLAN_STATUS_CHOICES), required=False)
|
site = forms.ModelChoiceField(
|
||||||
role = forms.ModelChoiceField(queryset=Role.objects.all(), required=False)
|
queryset=Site.objects.all(),
|
||||||
description = forms.CharField(max_length=100, required=False)
|
required=False
|
||||||
|
)
|
||||||
|
group = forms.ModelChoiceField(
|
||||||
|
queryset=VLANGroup.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
status = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(VLAN_STATUS_CHOICES),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
role = forms.ModelChoiceField(
|
||||||
|
queryset=Role.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['site', 'group', 'tenant', 'role', 'description']
|
nullable_fields = [
|
||||||
|
'site', 'group', 'tenant', 'role', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = VLAN
|
model = VLAN
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('vlans')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('vlans')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- Global --'
|
null_label='-- Global --'
|
||||||
)
|
)
|
||||||
group_id = FilterChoiceField(
|
group_id = FilterChoiceField(
|
||||||
queryset=VLANGroup.objects.annotate(filter_count=Count('vlans')),
|
queryset=VLANGroup.objects.annotate(
|
||||||
|
filter_count=Count('vlans')
|
||||||
|
),
|
||||||
label='VLAN group',
|
label='VLAN group',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('vlans')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('vlans')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -905,7 +1130,9 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
role = FilterChoiceField(
|
role = FilterChoiceField(
|
||||||
queryset=Role.objects.annotate(filter_count=Count('vlans')),
|
queryset=Role.objects.annotate(
|
||||||
|
filter_count=Count('vlans')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -916,18 +1143,21 @@ class VLANFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class ServiceForm(BootstrapMixin, CustomFieldForm):
|
class ServiceForm(BootstrapMixin, CustomFieldForm):
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Service
|
model = Service
|
||||||
fields = ['name', 'protocol', 'port', 'ipaddresses', 'description', 'tags']
|
fields = [
|
||||||
|
'name', 'protocol', 'port', 'ipaddresses', 'description', 'tags',
|
||||||
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be "
|
'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be "
|
||||||
"reachable via all IPs assigned to the device.",
|
"reachable via all IPs assigned to the device.",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
# Limit IP address choices to those assigned to interfaces of the parent device/VM
|
# Limit IP address choices to those assigned to interfaces of the parent device/VM
|
||||||
@ -960,10 +1190,27 @@ class ServiceFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
|
|
||||||
|
|
||||||
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
class ServiceBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Service.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
protocol = forms.ChoiceField(choices=add_blank_choice(IP_PROTOCOL_CHOICES), required=False)
|
queryset=Service.objects.all(),
|
||||||
port = forms.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(65535)], required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
description = forms.CharField(max_length=100, required=False)
|
)
|
||||||
|
protocol = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(IP_PROTOCOL_CHOICES),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
port = forms.IntegerField(
|
||||||
|
validators=[
|
||||||
|
MinValueValidator(1),
|
||||||
|
MaxValueValidator(65535),
|
||||||
|
],
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['site', 'group', 'tenant', 'role', 'description']
|
nullable_fields = [
|
||||||
|
'site', 'group', 'tenant', 'role', 'description',
|
||||||
|
]
|
||||||
|
@ -39,7 +39,9 @@ class SecretRoleForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SecretRole
|
model = SecretRole
|
||||||
fields = ['name', 'slug', 'users', 'groups']
|
fields = [
|
||||||
|
'name', 'slug', 'users', 'groups',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class SecretRoleCSVForm(forms.ModelForm):
|
class SecretRoleCSVForm(forms.ModelForm):
|
||||||
@ -62,7 +64,11 @@ class SecretForm(BootstrapMixin, CustomFieldForm):
|
|||||||
max_length=65535,
|
max_length=65535,
|
||||||
required=False,
|
required=False,
|
||||||
label='Plaintext',
|
label='Plaintext',
|
||||||
widget=forms.PasswordInput(attrs={'class': 'requires-session-key'})
|
widget=forms.PasswordInput(
|
||||||
|
attrs={
|
||||||
|
'class': 'requires-session-key',
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
plaintext2 = forms.CharField(
|
plaintext2 = forms.CharField(
|
||||||
max_length=65535,
|
max_length=65535,
|
||||||
@ -70,14 +76,17 @@ class SecretForm(BootstrapMixin, CustomFieldForm):
|
|||||||
label='Plaintext (verify)',
|
label='Plaintext (verify)',
|
||||||
widget=forms.PasswordInput()
|
widget=forms.PasswordInput()
|
||||||
)
|
)
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Secret
|
model = Secret
|
||||||
fields = ['role', 'name', 'plaintext', 'plaintext2', 'tags']
|
fields = [
|
||||||
|
'role', 'name', 'plaintext', 'plaintext2', 'tags',
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
# A plaintext value is required when creating a new Secret
|
# A plaintext value is required when creating a new Secret
|
||||||
@ -128,19 +137,35 @@ class SecretCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class SecretBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Secret.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
role = forms.ModelChoiceField(queryset=SecretRole.objects.all(), required=False)
|
queryset=Secret.objects.all(),
|
||||||
name = forms.CharField(max_length=100, required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
|
)
|
||||||
|
role = forms.ModelChoiceField(
|
||||||
|
queryset=SecretRole.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
name = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['name']
|
nullable_fields = [
|
||||||
|
'name',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class SecretFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Secret
|
model = Secret
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
role = FilterChoiceField(
|
role = FilterChoiceField(
|
||||||
queryset=SecretRole.objects.annotate(filter_count=Count('secrets')),
|
queryset=SecretRole.objects.annotate(
|
||||||
|
filter_count=Count('secrets')
|
||||||
|
),
|
||||||
to_field_name='slug'
|
to_field_name='slug'
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -169,5 +194,15 @@ class UserKeyForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class ActivateUserKeyForm(forms.Form):
|
class ActivateUserKeyForm(forms.Form):
|
||||||
_selected_action = forms.ModelMultipleChoiceField(queryset=UserKey.objects.all(), label='User Keys')
|
_selected_action = forms.ModelMultipleChoiceField(
|
||||||
secret_key = forms.CharField(label='Your private key', widget=forms.Textarea(attrs={'class': 'vLargeTextField'}))
|
queryset=UserKey.objects.all(),
|
||||||
|
label='User Keys'
|
||||||
|
)
|
||||||
|
secret_key = forms.CharField(
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
'class': 'vLargeTextField',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
label='Your private key'
|
||||||
|
)
|
||||||
|
@ -18,7 +18,9 @@ class TenantGroupForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TenantGroup
|
model = TenantGroup
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TenantGroupCSVForm(forms.ModelForm):
|
class TenantGroupCSVForm(forms.ModelForm):
|
||||||
@ -39,11 +41,15 @@ class TenantGroupCSVForm(forms.ModelForm):
|
|||||||
class TenantForm(BootstrapMixin, CustomFieldForm):
|
class TenantForm(BootstrapMixin, CustomFieldForm):
|
||||||
slug = SlugField()
|
slug = SlugField()
|
||||||
comments = CommentField()
|
comments = CommentField()
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Tenant
|
model = Tenant
|
||||||
fields = ['name', 'slug', 'group', 'description', 'comments', 'tags']
|
fields = [
|
||||||
|
'name', 'slug', 'group', 'description', 'comments', 'tags',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TenantCSVForm(forms.ModelForm):
|
class TenantCSVForm(forms.ModelForm):
|
||||||
@ -68,18 +74,31 @@ class TenantCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class TenantBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Tenant.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
group = forms.ModelChoiceField(queryset=TenantGroup.objects.all(), required=False)
|
queryset=Tenant.objects.all(),
|
||||||
|
widget=forms.MultipleHiddenInput()
|
||||||
|
)
|
||||||
|
group = forms.ModelChoiceField(
|
||||||
|
queryset=TenantGroup.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['group']
|
nullable_fields = [
|
||||||
|
'group',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class TenantFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Tenant
|
model = Tenant
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
group = FilterChoiceField(
|
group = FilterChoiceField(
|
||||||
queryset=TenantGroup.objects.annotate(filter_count=Count('tenants')),
|
queryset=TenantGroup.objects.annotate(
|
||||||
|
filter_count=Count('tenants')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -94,7 +113,10 @@ class TenancyForm(ChainedFieldsMixin, forms.Form):
|
|||||||
queryset=TenantGroup.objects.all(),
|
queryset=TenantGroup.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'tenant', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'tenant',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
tenant = ChainedModelChoiceField(
|
tenant = ChainedModelChoiceField(
|
||||||
|
@ -19,11 +19,16 @@ class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):
|
|||||||
|
|
||||||
|
|
||||||
class TokenForm(BootstrapMixin, forms.ModelForm):
|
class TokenForm(BootstrapMixin, forms.ModelForm):
|
||||||
key = forms.CharField(required=False, help_text="If no key is provided, one will be generated automatically.")
|
key = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
help_text="If no key is provided, one will be generated automatically."
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Token
|
model = Token
|
||||||
fields = ['key', 'write_enabled', 'expires', 'description']
|
fields = [
|
||||||
|
'key', 'write_enabled', 'expires', 'description',
|
||||||
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'expires': 'YYYY-MM-DD [HH:MM:SS]'
|
'expires': 'YYYY-MM-DD [HH:MM:SS]'
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,9 @@ class ClusterTypeForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ClusterType
|
model = ClusterType
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ClusterTypeCSVForm(forms.ModelForm):
|
class ClusterTypeCSVForm(forms.ModelForm):
|
||||||
@ -57,7 +59,9 @@ class ClusterGroupForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ClusterGroup
|
model = ClusterGroup
|
||||||
fields = ['name', 'slug']
|
fields = [
|
||||||
|
'name', 'slug',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ClusterGroupCSVForm(forms.ModelForm):
|
class ClusterGroupCSVForm(forms.ModelForm):
|
||||||
@ -76,12 +80,18 @@ class ClusterGroupCSVForm(forms.ModelForm):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class ClusterForm(BootstrapMixin, CustomFieldForm):
|
class ClusterForm(BootstrapMixin, CustomFieldForm):
|
||||||
comments = CommentField(widget=SmallTextarea)
|
comments = CommentField(
|
||||||
tags = TagField(required=False)
|
widget=SmallTextarea()
|
||||||
|
)
|
||||||
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Cluster
|
model = Cluster
|
||||||
fields = ['name', 'type', 'group', 'site', 'comments', 'tags']
|
fields = [
|
||||||
|
'name', 'type', 'group', 'site', 'comments', 'tags',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ClusterCSVForm(forms.ModelForm):
|
class ClusterCSVForm(forms.ModelForm):
|
||||||
@ -118,32 +128,54 @@ class ClusterCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class ClusterBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Cluster.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
type = forms.ModelChoiceField(queryset=ClusterType.objects.all(), required=False)
|
queryset=Cluster.objects.all(),
|
||||||
group = forms.ModelChoiceField(queryset=ClusterGroup.objects.all(), required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False)
|
)
|
||||||
comments = CommentField(widget=SmallTextarea)
|
type = forms.ModelChoiceField(
|
||||||
|
queryset=ClusterType.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
group = forms.ModelChoiceField(
|
||||||
|
queryset=ClusterGroup.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
site = forms.ModelChoiceField(
|
||||||
|
queryset=Site.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
comments = CommentField(
|
||||||
|
widget=SmallTextarea()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['group', 'site', 'comments']
|
nullable_fields = [
|
||||||
|
'group', 'site', 'comments',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class ClusterFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = Cluster
|
model = Cluster
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(required=False, label='Search')
|
||||||
type = FilterChoiceField(
|
type = FilterChoiceField(
|
||||||
queryset=ClusterType.objects.annotate(filter_count=Count('clusters')),
|
queryset=ClusterType.objects.annotate(
|
||||||
|
filter_count=Count('clusters')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
group = FilterChoiceField(
|
group = FilterChoiceField(
|
||||||
queryset=ClusterGroup.objects.annotate(filter_count=Count('clusters')),
|
queryset=ClusterGroup.objects.annotate(
|
||||||
|
filter_count=Count('clusters')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --',
|
null_label='-- None --',
|
||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('clusters')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('clusters')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --',
|
null_label='-- None --',
|
||||||
required=False,
|
required=False,
|
||||||
@ -155,7 +187,10 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
queryset=Region.objects.all(),
|
queryset=Region.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'site', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'site',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
site = ChainedModelChoiceField(
|
site = ChainedModelChoiceField(
|
||||||
@ -166,7 +201,9 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
required=False,
|
required=False,
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/dcim/sites/?region_id={{region}}',
|
api_url='/api/dcim/sites/?region_id={{region}}',
|
||||||
attrs={'filter-for': 'rack'}
|
attrs={
|
||||||
|
'filter-for': 'rack',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
rack = ChainedModelChoiceField(
|
rack = ChainedModelChoiceField(
|
||||||
@ -177,7 +214,10 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
required=False,
|
required=False,
|
||||||
widget=APISelect(
|
widget=APISelect(
|
||||||
api_url='/api/dcim/racks/?site_id={{site}}',
|
api_url='/api/dcim/racks/?site_id={{site}}',
|
||||||
attrs={'filter-for': 'devices', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'devices',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
devices = ChainedModelMultipleChoiceField(
|
devices = ChainedModelMultipleChoiceField(
|
||||||
@ -194,7 +234,9 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
fields = ['region', 'site', 'rack', 'devices']
|
fields = [
|
||||||
|
'region', 'site', 'rack', 'devices',
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, cluster, *args, **kwargs):
|
def __init__(self, cluster, *args, **kwargs):
|
||||||
|
|
||||||
@ -205,7 +247,6 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
self.fields['devices'].choices = []
|
self.fields['devices'].choices = []
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
# If the Cluster is assigned to a Site, all Devices must be assigned to that Site.
|
# If the Cluster is assigned to a Site, all Devices must be assigned to that Site.
|
||||||
@ -220,7 +261,10 @@ class ClusterAddDevicesForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
|
|||||||
|
|
||||||
|
|
||||||
class ClusterRemoveDevicesForm(ConfirmationForm):
|
class ClusterRemoveDevicesForm(ConfirmationForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=Device.objects.all(),
|
||||||
|
widget=forms.MultipleHiddenInput()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -232,7 +276,10 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
queryset=ClusterGroup.objects.all(),
|
queryset=ClusterGroup.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
attrs={'filter-for': 'cluster', 'nullable': 'true'}
|
attrs={
|
||||||
|
'filter-for': 'cluster',
|
||||||
|
'nullable': 'true',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
cluster = ChainedModelChoiceField(
|
cluster = ChainedModelChoiceField(
|
||||||
@ -244,8 +291,12 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
api_url='/api/virtualization/clusters/?group_id={{cluster_group}}'
|
api_url='/api/virtualization/clusters/?group_id={{cluster_group}}'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
local_context_data = JSONField(required=False)
|
required=False
|
||||||
|
)
|
||||||
|
local_context_data = JSONField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VirtualMachine
|
model = VirtualMachine
|
||||||
@ -254,7 +305,8 @@ class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm):
|
|||||||
'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data',
|
'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data',
|
||||||
]
|
]
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'local_context_data': "Local config context data overwrites all sources contexts in the final rendered config context",
|
'local_context_data': "Local config context data overwrites all sources contexts in the final rendered "
|
||||||
|
"config context",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -319,7 +371,9 @@ class VirtualMachineCSVForm(forms.ModelForm):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
role = forms.ModelChoiceField(
|
role = forms.ModelChoiceField(
|
||||||
queryset=DeviceRole.objects.filter(vm_role=True),
|
queryset=DeviceRole.objects.filter(
|
||||||
|
vm_role=True
|
||||||
|
),
|
||||||
required=False,
|
required=False,
|
||||||
to_field_name='name',
|
to_field_name='name',
|
||||||
help_text='Name of functional role',
|
help_text='Name of functional role',
|
||||||
@ -352,24 +406,61 @@ class VirtualMachineCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
class VirtualMachineBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
status = forms.ChoiceField(choices=add_blank_choice(VM_STATUS_CHOICES), required=False, initial='')
|
queryset=VirtualMachine.objects.all(),
|
||||||
cluster = forms.ModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
widget=forms.MultipleHiddenInput()
|
||||||
role = forms.ModelChoiceField(queryset=DeviceRole.objects.filter(vm_role=True), required=False)
|
)
|
||||||
tenant = forms.ModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
status = forms.ChoiceField(
|
||||||
platform = forms.ModelChoiceField(queryset=Platform.objects.all(), required=False)
|
choices=add_blank_choice(VM_STATUS_CHOICES),
|
||||||
vcpus = forms.IntegerField(required=False, label='vCPUs')
|
required=False,
|
||||||
memory = forms.IntegerField(required=False, label='Memory (MB)')
|
initial=''
|
||||||
disk = forms.IntegerField(required=False, label='Disk (GB)')
|
)
|
||||||
comments = CommentField(widget=SmallTextarea)
|
cluster = forms.ModelChoiceField(
|
||||||
|
queryset=Cluster.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
role = forms.ModelChoiceField(
|
||||||
|
queryset=DeviceRole.objects.filter(
|
||||||
|
vm_role=True
|
||||||
|
),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
tenant = forms.ModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
platform = forms.ModelChoiceField(
|
||||||
|
queryset=Platform.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
vcpus = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='vCPUs'
|
||||||
|
)
|
||||||
|
memory = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='Memory (MB)'
|
||||||
|
)
|
||||||
|
disk = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
label='Disk (GB)'
|
||||||
|
)
|
||||||
|
comments = CommentField(
|
||||||
|
widget=SmallTextarea()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments']
|
nullable_fields = [
|
||||||
|
'role', 'tenant', 'platform', 'vcpus', 'memory', 'disk', 'comments',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
||||||
model = VirtualMachine
|
model = VirtualMachine
|
||||||
q = forms.CharField(required=False, label='Search')
|
q = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='Search'
|
||||||
|
)
|
||||||
cluster_group = FilterChoiceField(
|
cluster_group = FilterChoiceField(
|
||||||
queryset=ClusterGroup.objects.all(),
|
queryset=ClusterGroup.objects.all(),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
@ -381,7 +472,9 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
cluster_id = FilterChoiceField(
|
cluster_id = FilterChoiceField(
|
||||||
queryset=Cluster.objects.annotate(filter_count=Count('virtual_machines')),
|
queryset=Cluster.objects.annotate(
|
||||||
|
filter_count=Count('virtual_machines')
|
||||||
|
),
|
||||||
label='Cluster'
|
label='Cluster'
|
||||||
)
|
)
|
||||||
region = FilterTreeNodeMultipleChoiceField(
|
region = FilterTreeNodeMultipleChoiceField(
|
||||||
@ -390,12 +483,18 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False,
|
required=False,
|
||||||
)
|
)
|
||||||
site = FilterChoiceField(
|
site = FilterChoiceField(
|
||||||
queryset=Site.objects.annotate(filter_count=Count('clusters__virtual_machines')),
|
queryset=Site.objects.annotate(
|
||||||
|
filter_count=Count('clusters__virtual_machines')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
role = FilterChoiceField(
|
role = FilterChoiceField(
|
||||||
queryset=DeviceRole.objects.filter(vm_role=True).annotate(filter_count=Count('virtual_machines')),
|
queryset=DeviceRole.objects.filter(
|
||||||
|
vm_role=True
|
||||||
|
).annotate(
|
||||||
|
filter_count=Count('virtual_machines')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -406,12 +505,16 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
tenant = FilterChoiceField(
|
tenant = FilterChoiceField(
|
||||||
queryset=Tenant.objects.annotate(filter_count=Count('virtual_machines')),
|
queryset=Tenant.objects.annotate(
|
||||||
|
filter_count=Count('virtual_machines')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
platform = FilterChoiceField(
|
platform = FilterChoiceField(
|
||||||
queryset=Platform.objects.annotate(filter_count=Count('virtual_machines')),
|
queryset=Platform.objects.annotate(
|
||||||
|
filter_count=Count('virtual_machines')
|
||||||
|
),
|
||||||
to_field_name='slug',
|
to_field_name='slug',
|
||||||
null_label='-- None --'
|
null_label='-- None --'
|
||||||
)
|
)
|
||||||
@ -422,7 +525,9 @@ class VirtualMachineFilterForm(BootstrapMixin, CustomFieldFilterForm):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class InterfaceForm(BootstrapMixin, forms.ModelForm):
|
class InterfaceForm(BootstrapMixin, forms.ModelForm):
|
||||||
tags = TagField(required=False)
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Interface
|
model = Interface
|
||||||
@ -442,7 +547,6 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
|
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
# Validate VLAN assignments
|
# Validate VLAN assignments
|
||||||
@ -460,13 +564,34 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class InterfaceCreateForm(ComponentForm):
|
class InterfaceCreateForm(ComponentForm):
|
||||||
name_pattern = ExpandableNameField(label='Name')
|
name_pattern = ExpandableNameField(
|
||||||
form_factor = forms.ChoiceField(choices=VIFACE_FF_CHOICES, initial=IFACE_FF_VIRTUAL, widget=forms.HiddenInput())
|
label='Name'
|
||||||
enabled = forms.BooleanField(required=False)
|
)
|
||||||
mtu = forms.IntegerField(required=False, min_value=1, max_value=32767, label='MTU')
|
form_factor = forms.ChoiceField(
|
||||||
mac_address = forms.CharField(required=False, label='MAC Address')
|
choices=VIFACE_FF_CHOICES,
|
||||||
description = forms.CharField(max_length=100, required=False)
|
initial=IFACE_FF_VIRTUAL,
|
||||||
tags = TagField(required=False)
|
widget=forms.HiddenInput()
|
||||||
|
)
|
||||||
|
enabled = forms.BooleanField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
mtu = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
min_value=1,
|
||||||
|
max_value=32767,
|
||||||
|
label='MTU'
|
||||||
|
)
|
||||||
|
mac_address = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label='MAC Address'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
tags = TagField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
@ -478,13 +603,29 @@ class InterfaceCreateForm(ComponentForm):
|
|||||||
|
|
||||||
|
|
||||||
class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
enabled = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect)
|
queryset=Interface.objects.all(),
|
||||||
mtu = forms.IntegerField(required=False, min_value=1, max_value=32767, label='MTU')
|
widget=forms.MultipleHiddenInput()
|
||||||
description = forms.CharField(max_length=100, required=False)
|
)
|
||||||
|
enabled = forms.NullBooleanField(
|
||||||
|
required=False,
|
||||||
|
widget=BulkEditNullBooleanSelect()
|
||||||
|
)
|
||||||
|
mtu = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
min_value=1,
|
||||||
|
max_value=32767,
|
||||||
|
label='MTU'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['mtu', 'description']
|
nullable_fields = [
|
||||||
|
'mtu', 'description',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -492,12 +633,32 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm):
|
|||||||
#
|
#
|
||||||
|
|
||||||
class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
|
class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
|
||||||
pk = forms.ModelMultipleChoiceField(queryset=VirtualMachine.objects.all(), widget=forms.MultipleHiddenInput)
|
pk = forms.ModelMultipleChoiceField(
|
||||||
name_pattern = ExpandableNameField(label='Name')
|
queryset=VirtualMachine.objects.all(),
|
||||||
|
widget=forms.MultipleHiddenInput()
|
||||||
|
)
|
||||||
|
name_pattern = ExpandableNameField(
|
||||||
|
label='Name'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VirtualMachineBulkAddInterfaceForm(VirtualMachineBulkAddComponentForm):
|
class VirtualMachineBulkAddInterfaceForm(VirtualMachineBulkAddComponentForm):
|
||||||
form_factor = forms.ChoiceField(choices=VIFACE_FF_CHOICES, initial=IFACE_FF_VIRTUAL, widget=forms.HiddenInput())
|
form_factor = forms.ChoiceField(
|
||||||
enabled = forms.BooleanField(required=False, initial=True)
|
choices=VIFACE_FF_CHOICES,
|
||||||
mtu = forms.IntegerField(required=False, min_value=1, max_value=32767, label='MTU')
|
initial=IFACE_FF_VIRTUAL,
|
||||||
description = forms.CharField(max_length=100, required=False)
|
widget=forms.HiddenInput()
|
||||||
|
)
|
||||||
|
enabled = forms.BooleanField(
|
||||||
|
required=False,
|
||||||
|
initial=True
|
||||||
|
)
|
||||||
|
mtu = forms.IntegerField(
|
||||||
|
required=False,
|
||||||
|
min_value=1,
|
||||||
|
max_value=32767,
|
||||||
|
label='MTU'
|
||||||
|
)
|
||||||
|
description = forms.CharField(
|
||||||
|
max_length=100,
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user