mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Extend VLANGroup to support cluster/cluster group assignment
This commit is contained in:
@ -552,6 +552,12 @@ class VLANGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
|||||||
rack = django_filters.NumberFilter(
|
rack = django_filters.NumberFilter(
|
||||||
method='filter_scope'
|
method='filter_scope'
|
||||||
)
|
)
|
||||||
|
clustergroup = django_filters.NumberFilter(
|
||||||
|
method='filter_scope'
|
||||||
|
)
|
||||||
|
cluster = django_filters.NumberFilter(
|
||||||
|
method='filter_scope'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLANGroup
|
model = VLANGroup
|
||||||
@ -559,7 +565,7 @@ class VLANGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
|
|||||||
|
|
||||||
def filter_scope(self, queryset, name, value):
|
def filter_scope(self, queryset, name, value):
|
||||||
return queryset.filter(
|
return queryset.filter(
|
||||||
scope_type=ContentType.objects.get(app_label='dcim', model=name),
|
scope_type=ContentType.objects.get(model=name),
|
||||||
scope_id=value
|
scope_id=value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
|
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
|
||||||
@ -14,7 +13,7 @@ from utilities.forms import (
|
|||||||
DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField, NumericArrayField,
|
DynamicModelChoiceField, DynamicModelMultipleChoiceField, ExpandableIPAddressField, NumericArrayField,
|
||||||
ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
|
ReturnURLForm, SlugField, StaticSelect2, StaticSelect2Multiple, TagFilterField, BOOLEAN_WITH_BLANK_CHOICES,
|
||||||
)
|
)
|
||||||
from virtualization.models import Cluster, VirtualMachine, VMInterface
|
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .constants import *
|
from .constants import *
|
||||||
from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF
|
from .models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF
|
||||||
@ -1153,17 +1152,28 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
'location_id': '$location',
|
'location_id': '$location',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
cluster_group = DynamicModelChoiceField(
|
||||||
|
queryset=ClusterGroup.objects.all(),
|
||||||
|
required=False,
|
||||||
|
initial_params={
|
||||||
|
'clusters': '$cluster'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
cluster = DynamicModelChoiceField(
|
||||||
|
queryset=Cluster.objects.all(),
|
||||||
|
required=False,
|
||||||
|
query_params={
|
||||||
|
'group_id': '$cluster_group',
|
||||||
|
}
|
||||||
|
)
|
||||||
slug = SlugField()
|
slug = SlugField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLANGroup
|
model = VLANGroup
|
||||||
fields = [
|
fields = [
|
||||||
'name', 'slug', 'description', 'region', 'site_group', 'site', 'location', 'rack',
|
'name', 'slug', 'description', 'region', 'site_group', 'site', 'location', 'rack', 'cluster_group',
|
||||||
|
'cluster',
|
||||||
]
|
]
|
||||||
fieldsets = (
|
|
||||||
('VLAN Group', ('name', 'slug', 'description')),
|
|
||||||
('Scope', ('region', 'site_group', 'site', 'location', 'rack')),
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
instance = kwargs.get('instance')
|
instance = kwargs.get('instance')
|
||||||
@ -1180,6 +1190,10 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
initial['site_group'] = instance.scope
|
initial['site_group'] = instance.scope
|
||||||
elif type(instance.scope) is Region:
|
elif type(instance.scope) is Region:
|
||||||
initial['region'] = instance.scope
|
initial['region'] = instance.scope
|
||||||
|
elif type(instance.scope) is Cluster:
|
||||||
|
initial['cluster'] = instance.scope
|
||||||
|
elif type(instance.scope) is ClusterGroup:
|
||||||
|
initial['cluster_group'] = instance.scope
|
||||||
|
|
||||||
kwargs['initial'] = initial
|
kwargs['initial'] = initial
|
||||||
|
|
||||||
@ -1189,8 +1203,10 @@ class VLANGroupForm(BootstrapMixin, CustomFieldModelForm):
|
|||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
# Assign scope object
|
# Assign scope object
|
||||||
self.instance.scope = self.cleaned_data['rack'] or self.cleaned_data['location'] or self.cleaned_data['site'] \
|
self.instance.scope = self.cleaned_data['rack'] or self.cleaned_data['location'] or \
|
||||||
or self.cleaned_data['site_group'] or self.cleaned_data['region'] or None
|
self.cleaned_data['site'] or self.cleaned_data['site_group'] or \
|
||||||
|
self.cleaned_data['region'] or self.cleaned_data['cluster'] or \
|
||||||
|
self.cleaned_data['cluster_group'] or None
|
||||||
|
|
||||||
|
|
||||||
class VLANGroupCSVForm(CustomFieldModelCSVForm):
|
class VLANGroupCSVForm(CustomFieldModelCSVForm):
|
||||||
|
@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
|||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='vlangroup',
|
model_name='vlangroup',
|
||||||
name='scope_type',
|
name='scope_type',
|
||||||
field=models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ['region', 'sitegroup', 'site', 'location', 'rack'])), null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'),
|
field=models.ForeignKey(blank=True, limit_choices_to=models.Q(model__in=['region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster']), null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype'),
|
||||||
),
|
),
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name='vlangroup',
|
name='vlangroup',
|
||||||
|
@ -35,8 +35,7 @@ class VLANGroup(OrganizationalModel):
|
|||||||
to=ContentType,
|
to=ContentType,
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
limit_choices_to=Q(
|
limit_choices_to=Q(
|
||||||
app_label='dcim',
|
model__in=['region', 'sitegroup', 'site', 'location', 'rack', 'clustergroup', 'cluster']
|
||||||
model__in=['region', 'sitegroup', 'site', 'location', 'rack']
|
|
||||||
),
|
),
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
|
@ -642,6 +642,7 @@ class VLANGroupListView(generic.ObjectListView):
|
|||||||
class VLANGroupEditView(generic.ObjectEditView):
|
class VLANGroupEditView(generic.ObjectEditView):
|
||||||
queryset = VLANGroup.objects.all()
|
queryset = VLANGroup.objects.all()
|
||||||
model_form = forms.VLANGroupForm
|
model_form = forms.VLANGroupForm
|
||||||
|
template_name = 'ipam/vlangroup_edit.html'
|
||||||
|
|
||||||
|
|
||||||
class VLANGroupDeleteView(generic.ObjectDeleteView):
|
class VLANGroupDeleteView(generic.ObjectDeleteView):
|
||||||
@ -655,7 +656,7 @@ class VLANGroupBulkImportView(generic.BulkImportView):
|
|||||||
|
|
||||||
|
|
||||||
class VLANGroupBulkDeleteView(generic.BulkDeleteView):
|
class VLANGroupBulkDeleteView(generic.BulkDeleteView):
|
||||||
queryset = VLANGroup.objects.prefetch_related('site').annotate(
|
queryset = VLANGroup.objects.annotate(
|
||||||
vlan_count=count_related(VLAN, 'group')
|
vlan_count=count_related(VLAN, 'group')
|
||||||
)
|
)
|
||||||
filterset = filters.VLANGroupFilterSet
|
filterset = filters.VLANGroupFilterSet
|
||||||
|
49
netbox/templates/ipam/vlangroup_edit.html
Normal file
49
netbox/templates/ipam/vlangroup_edit.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{% extends 'generic/object_edit.html' %}
|
||||||
|
{% load form_helpers %}
|
||||||
|
{% load helpers %}
|
||||||
|
|
||||||
|
{% block form %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>VLAN Group</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{% render_field form.name %}
|
||||||
|
{% render_field form.slug %}
|
||||||
|
{% render_field form.description %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<strong>Scope</strong>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{% with virtual_tab_active=form.initial.cluster %}
|
||||||
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
|
<li role="presentation"{% if not virtual_tab_active %} class="active"{% endif %}><a href="#physical" role="tab" data-toggle="tab">Physical</a></li>
|
||||||
|
<li role="presentation"{% if virtual_tab_active %} class="active"{% endif %}><a href="#virtual" role="tab" data-toggle="tab">Virtual</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane{% if not virtual_tab_active %} active{% endif %}" id="physical">
|
||||||
|
{% render_field form.region %}
|
||||||
|
{% render_field form.site_group %}
|
||||||
|
{% render_field form.site %}
|
||||||
|
{% render_field form.location %}
|
||||||
|
{% render_field form.rack %}
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane{% if virtual_tab_active %} active{% endif %}" id="virtual">
|
||||||
|
{% render_field form.cluster_group %}
|
||||||
|
{% render_field form.cluster %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="help-block">The VLAN group will be limited in scope to the most-specific object selected above.</span>
|
||||||
|
{% endwith %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if form.custom_fields %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>Custom Fields</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{% render_custom_fields form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
Reference in New Issue
Block a user