mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Prefetch the Tenant Group in views which allows its table to be configured by the user. This decreases the amount of database queries that are required to fetch the data.
1153 lines
35 KiB
Python
1153 lines
35 KiB
Python
from django.contrib.contenttypes.models import ContentType
|
|
from django.db.models import Prefetch
|
|
from django.db.models.expressions import RawSQL
|
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
from django.urls import reverse
|
|
|
|
from circuits.models import Provider, Circuit
|
|
from circuits.tables import ProviderTable
|
|
from dcim.filtersets import InterfaceFilterSet
|
|
from dcim.models import Interface, Site, Device
|
|
from dcim.tables import SiteTable
|
|
from netbox.views import generic
|
|
from utilities.utils import count_related
|
|
from virtualization.filtersets import VMInterfaceFilterSet
|
|
from virtualization.models import VMInterface, VirtualMachine
|
|
from . import filtersets, forms, tables
|
|
from .constants import *
|
|
from .models import *
|
|
from .models import ASN
|
|
from .utils import add_requested_prefixes, add_available_ipaddresses, add_available_vlans
|
|
|
|
|
|
#
|
|
# VRFs
|
|
#
|
|
|
|
class VRFListView(generic.ObjectListView):
|
|
queryset = VRF.objects.all()
|
|
filterset = filtersets.VRFFilterSet
|
|
filterset_form = forms.VRFFilterForm
|
|
table = tables.VRFTable
|
|
|
|
|
|
class VRFView(generic.ObjectView):
|
|
queryset = VRF.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
prefix_count = Prefix.objects.restrict(request.user, 'view').filter(vrf=instance).count()
|
|
ipaddress_count = IPAddress.objects.restrict(request.user, 'view').filter(vrf=instance).count()
|
|
|
|
import_targets_table = tables.RouteTargetTable(
|
|
instance.import_targets.prefetch_related('tenant'),
|
|
orderable=False
|
|
)
|
|
export_targets_table = tables.RouteTargetTable(
|
|
instance.export_targets.prefetch_related('tenant'),
|
|
orderable=False
|
|
)
|
|
|
|
return {
|
|
'prefix_count': prefix_count,
|
|
'ipaddress_count': ipaddress_count,
|
|
'import_targets_table': import_targets_table,
|
|
'export_targets_table': export_targets_table,
|
|
}
|
|
|
|
|
|
class VRFEditView(generic.ObjectEditView):
|
|
queryset = VRF.objects.all()
|
|
form = forms.VRFForm
|
|
|
|
|
|
class VRFDeleteView(generic.ObjectDeleteView):
|
|
queryset = VRF.objects.all()
|
|
|
|
|
|
class VRFBulkImportView(generic.BulkImportView):
|
|
queryset = VRF.objects.all()
|
|
model_form = forms.VRFCSVForm
|
|
table = tables.VRFTable
|
|
|
|
|
|
class VRFBulkEditView(generic.BulkEditView):
|
|
queryset = VRF.objects.prefetch_related('tenant')
|
|
filterset = filtersets.VRFFilterSet
|
|
table = tables.VRFTable
|
|
form = forms.VRFBulkEditForm
|
|
|
|
|
|
class VRFBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = VRF.objects.prefetch_related('tenant')
|
|
filterset = filtersets.VRFFilterSet
|
|
table = tables.VRFTable
|
|
|
|
|
|
#
|
|
# Route targets
|
|
#
|
|
|
|
class RouteTargetListView(generic.ObjectListView):
|
|
queryset = RouteTarget.objects.all()
|
|
filterset = filtersets.RouteTargetFilterSet
|
|
filterset_form = forms.RouteTargetFilterForm
|
|
table = tables.RouteTargetTable
|
|
|
|
|
|
class RouteTargetView(generic.ObjectView):
|
|
queryset = RouteTarget.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
importing_vrfs_table = tables.VRFTable(
|
|
instance.importing_vrfs.prefetch_related('tenant'),
|
|
orderable=False
|
|
)
|
|
exporting_vrfs_table = tables.VRFTable(
|
|
instance.exporting_vrfs.prefetch_related('tenant'),
|
|
orderable=False
|
|
)
|
|
|
|
return {
|
|
'importing_vrfs_table': importing_vrfs_table,
|
|
'exporting_vrfs_table': exporting_vrfs_table,
|
|
}
|
|
|
|
|
|
class RouteTargetEditView(generic.ObjectEditView):
|
|
queryset = RouteTarget.objects.all()
|
|
form = forms.RouteTargetForm
|
|
|
|
|
|
class RouteTargetDeleteView(generic.ObjectDeleteView):
|
|
queryset = RouteTarget.objects.all()
|
|
|
|
|
|
class RouteTargetBulkImportView(generic.BulkImportView):
|
|
queryset = RouteTarget.objects.all()
|
|
model_form = forms.RouteTargetCSVForm
|
|
table = tables.RouteTargetTable
|
|
|
|
|
|
class RouteTargetBulkEditView(generic.BulkEditView):
|
|
queryset = RouteTarget.objects.prefetch_related('tenant')
|
|
filterset = filtersets.RouteTargetFilterSet
|
|
table = tables.RouteTargetTable
|
|
form = forms.RouteTargetBulkEditForm
|
|
|
|
|
|
class RouteTargetBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = RouteTarget.objects.prefetch_related('tenant')
|
|
filterset = filtersets.RouteTargetFilterSet
|
|
table = tables.RouteTargetTable
|
|
|
|
|
|
#
|
|
# RIRs
|
|
#
|
|
|
|
class RIRListView(generic.ObjectListView):
|
|
queryset = RIR.objects.annotate(
|
|
aggregate_count=count_related(Aggregate, 'rir')
|
|
)
|
|
filterset = filtersets.RIRFilterSet
|
|
filterset_form = forms.RIRFilterForm
|
|
table = tables.RIRTable
|
|
|
|
|
|
class RIRView(generic.ObjectView):
|
|
queryset = RIR.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
aggregates = Aggregate.objects.restrict(request.user, 'view').filter(rir=instance).annotate(
|
|
child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ())
|
|
)
|
|
aggregates_table = tables.AggregateTable(aggregates, user=request.user, exclude=('rir', 'utilization'))
|
|
aggregates_table.configure(request)
|
|
|
|
return {
|
|
'aggregates_table': aggregates_table,
|
|
}
|
|
|
|
|
|
class RIREditView(generic.ObjectEditView):
|
|
queryset = RIR.objects.all()
|
|
form = forms.RIRForm
|
|
|
|
|
|
class RIRDeleteView(generic.ObjectDeleteView):
|
|
queryset = RIR.objects.all()
|
|
|
|
|
|
class RIRBulkImportView(generic.BulkImportView):
|
|
queryset = RIR.objects.all()
|
|
model_form = forms.RIRCSVForm
|
|
table = tables.RIRTable
|
|
|
|
|
|
class RIRBulkEditView(generic.BulkEditView):
|
|
queryset = RIR.objects.annotate(
|
|
aggregate_count=count_related(Aggregate, 'rir')
|
|
)
|
|
filterset = filtersets.RIRFilterSet
|
|
table = tables.RIRTable
|
|
form = forms.RIRBulkEditForm
|
|
|
|
|
|
class RIRBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = RIR.objects.annotate(
|
|
aggregate_count=count_related(Aggregate, 'rir')
|
|
)
|
|
filterset = filtersets.RIRFilterSet
|
|
table = tables.RIRTable
|
|
|
|
|
|
#
|
|
# ASNs
|
|
#
|
|
|
|
class ASNListView(generic.ObjectListView):
|
|
queryset = ASN.objects.annotate(
|
|
site_count=count_related(Site, 'asns'),
|
|
provider_count=count_related(Provider, 'asns')
|
|
)
|
|
filterset = filtersets.ASNFilterSet
|
|
filterset_form = forms.ASNFilterForm
|
|
table = tables.ASNTable
|
|
|
|
|
|
class ASNView(generic.ObjectView):
|
|
queryset = ASN.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
# Gather assigned Sites
|
|
sites = instance.sites.restrict(request.user, 'view')
|
|
sites_table = SiteTable(sites, user=request.user)
|
|
sites_table.configure(request)
|
|
|
|
# Gather assigned Providers
|
|
providers = instance.providers.restrict(request.user, 'view').annotate(
|
|
count_circuits=count_related(Circuit, 'provider')
|
|
)
|
|
providers_table = ProviderTable(providers, user=request.user)
|
|
providers_table.configure(request)
|
|
|
|
return {
|
|
'sites_table': sites_table,
|
|
'sites_count': sites.count(),
|
|
'providers_table': providers_table,
|
|
'providers_count': providers.count(),
|
|
}
|
|
|
|
|
|
class ASNEditView(generic.ObjectEditView):
|
|
queryset = ASN.objects.all()
|
|
form = forms.ASNForm
|
|
|
|
|
|
class ASNDeleteView(generic.ObjectDeleteView):
|
|
queryset = ASN.objects.all()
|
|
|
|
|
|
class ASNBulkImportView(generic.BulkImportView):
|
|
queryset = ASN.objects.all()
|
|
model_form = forms.ASNCSVForm
|
|
table = tables.ASNTable
|
|
|
|
|
|
class ASNBulkEditView(generic.BulkEditView):
|
|
queryset = ASN.objects.annotate(
|
|
site_count=count_related(Site, 'asns')
|
|
)
|
|
filterset = filtersets.ASNFilterSet
|
|
table = tables.ASNTable
|
|
form = forms.ASNBulkEditForm
|
|
|
|
|
|
class ASNBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = ASN.objects.annotate(
|
|
site_count=count_related(Site, 'asns')
|
|
)
|
|
filterset = filtersets.ASNFilterSet
|
|
table = tables.ASNTable
|
|
|
|
|
|
#
|
|
# Aggregates
|
|
#
|
|
|
|
class AggregateListView(generic.ObjectListView):
|
|
queryset = Aggregate.objects.annotate(
|
|
child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ())
|
|
)
|
|
filterset = filtersets.AggregateFilterSet
|
|
filterset_form = forms.AggregateFilterForm
|
|
table = tables.AggregateTable
|
|
|
|
|
|
class AggregateView(generic.ObjectView):
|
|
queryset = Aggregate.objects.all()
|
|
|
|
|
|
class AggregatePrefixesView(generic.ObjectChildrenView):
|
|
queryset = Aggregate.objects.all()
|
|
child_model = Prefix
|
|
table = tables.PrefixTable
|
|
filterset = filtersets.PrefixFilterSet
|
|
template_name = 'ipam/aggregate/prefixes.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return Prefix.objects.restrict(request.user, 'view').filter(
|
|
prefix__net_contained_or_equal=str(parent.prefix)
|
|
).prefetch_related('site', 'role', 'tenant', 'tenant__group', 'vlan')
|
|
|
|
def prep_table_data(self, request, queryset, parent):
|
|
# Determine whether to show assigned prefixes, available prefixes, or both
|
|
show_available = bool(request.GET.get('show_available', 'true') == 'true')
|
|
show_assigned = bool(request.GET.get('show_assigned', 'true') == 'true')
|
|
|
|
return add_requested_prefixes(parent.prefix, queryset, show_available, show_assigned)
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'bulk_querystring': f'within={instance.prefix}',
|
|
'active_tab': 'prefixes',
|
|
'first_available_prefix': instance.get_first_available_prefix(),
|
|
'show_available': bool(request.GET.get('show_available', 'true') == 'true'),
|
|
'show_assigned': bool(request.GET.get('show_assigned', 'true') == 'true'),
|
|
}
|
|
|
|
|
|
class AggregateEditView(generic.ObjectEditView):
|
|
queryset = Aggregate.objects.all()
|
|
form = forms.AggregateForm
|
|
|
|
|
|
class AggregateDeleteView(generic.ObjectDeleteView):
|
|
queryset = Aggregate.objects.all()
|
|
|
|
|
|
class AggregateBulkImportView(generic.BulkImportView):
|
|
queryset = Aggregate.objects.all()
|
|
model_form = forms.AggregateCSVForm
|
|
table = tables.AggregateTable
|
|
|
|
|
|
class AggregateBulkEditView(generic.BulkEditView):
|
|
queryset = Aggregate.objects.prefetch_related('rir')
|
|
filterset = filtersets.AggregateFilterSet
|
|
table = tables.AggregateTable
|
|
form = forms.AggregateBulkEditForm
|
|
|
|
|
|
class AggregateBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = Aggregate.objects.prefetch_related('rir')
|
|
filterset = filtersets.AggregateFilterSet
|
|
table = tables.AggregateTable
|
|
|
|
|
|
#
|
|
# Prefix/VLAN roles
|
|
#
|
|
|
|
class RoleListView(generic.ObjectListView):
|
|
queryset = Role.objects.annotate(
|
|
prefix_count=count_related(Prefix, 'role'),
|
|
iprange_count=count_related(IPRange, 'role'),
|
|
vlan_count=count_related(VLAN, 'role')
|
|
)
|
|
filterset = filtersets.RoleFilterSet
|
|
filterset_form = forms.RoleFilterForm
|
|
table = tables.RoleTable
|
|
|
|
|
|
class RoleView(generic.ObjectView):
|
|
queryset = Role.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
prefixes = Prefix.objects.restrict(request.user, 'view').filter(
|
|
role=instance
|
|
)
|
|
|
|
prefixes_table = tables.PrefixTable(prefixes, user=request.user, exclude=('role', 'utilization'))
|
|
prefixes_table.configure(request)
|
|
|
|
return {
|
|
'prefixes_table': prefixes_table,
|
|
}
|
|
|
|
|
|
class RoleEditView(generic.ObjectEditView):
|
|
queryset = Role.objects.all()
|
|
form = forms.RoleForm
|
|
|
|
|
|
class RoleDeleteView(generic.ObjectDeleteView):
|
|
queryset = Role.objects.all()
|
|
|
|
|
|
class RoleBulkImportView(generic.BulkImportView):
|
|
queryset = Role.objects.all()
|
|
model_form = forms.RoleCSVForm
|
|
table = tables.RoleTable
|
|
|
|
|
|
class RoleBulkEditView(generic.BulkEditView):
|
|
queryset = Role.objects.all()
|
|
filterset = filtersets.RoleFilterSet
|
|
table = tables.RoleTable
|
|
form = forms.RoleBulkEditForm
|
|
|
|
|
|
class RoleBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = Role.objects.all()
|
|
table = tables.RoleTable
|
|
|
|
|
|
#
|
|
# Prefixes
|
|
#
|
|
|
|
class PrefixListView(generic.ObjectListView):
|
|
queryset = Prefix.objects.all()
|
|
filterset = filtersets.PrefixFilterSet
|
|
filterset_form = forms.PrefixFilterForm
|
|
table = tables.PrefixTable
|
|
template_name = 'ipam/prefix_list.html'
|
|
|
|
|
|
class PrefixView(generic.ObjectView):
|
|
queryset = Prefix.objects.prefetch_related('vrf', 'site__region', 'tenant__group', 'vlan__group', 'role')
|
|
|
|
def get_extra_context(self, request, instance):
|
|
try:
|
|
aggregate = Aggregate.objects.restrict(request.user, 'view').get(
|
|
prefix__net_contains_or_equals=str(instance.prefix)
|
|
)
|
|
except Aggregate.DoesNotExist:
|
|
aggregate = None
|
|
|
|
# Parent prefixes table
|
|
parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter(
|
|
Q(vrf=instance.vrf) | Q(vrf__isnull=True)
|
|
).filter(
|
|
prefix__net_contains=str(instance.prefix)
|
|
).prefetch_related(
|
|
'site', 'role', 'tenant'
|
|
)
|
|
parent_prefix_table = tables.PrefixTable(
|
|
list(parent_prefixes),
|
|
exclude=('vrf', 'utilization'),
|
|
orderable=False
|
|
)
|
|
|
|
# Duplicate prefixes table
|
|
duplicate_prefixes = Prefix.objects.restrict(request.user, 'view').filter(
|
|
vrf=instance.vrf, prefix=str(instance.prefix)
|
|
).exclude(
|
|
pk=instance.pk
|
|
).prefetch_related(
|
|
'site', 'role'
|
|
)
|
|
duplicate_prefix_table = tables.PrefixTable(
|
|
list(duplicate_prefixes),
|
|
exclude=('vrf', 'utilization'),
|
|
orderable=False
|
|
)
|
|
|
|
return {
|
|
'aggregate': aggregate,
|
|
'parent_prefix_table': parent_prefix_table,
|
|
'duplicate_prefix_table': duplicate_prefix_table,
|
|
}
|
|
|
|
|
|
class PrefixPrefixesView(generic.ObjectChildrenView):
|
|
queryset = Prefix.objects.all()
|
|
child_model = Prefix
|
|
table = tables.PrefixTable
|
|
filterset = filtersets.PrefixFilterSet
|
|
template_name = 'ipam/prefix/prefixes.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_child_prefixes().restrict(request.user, 'view').prefetch_related(
|
|
'site', 'vrf', 'vlan', 'role', 'tenant', 'tenant__group'
|
|
)
|
|
|
|
def prep_table_data(self, request, queryset, parent):
|
|
# Determine whether to show assigned prefixes, available prefixes, or both
|
|
show_available = bool(request.GET.get('show_available', 'true') == 'true')
|
|
show_assigned = bool(request.GET.get('show_assigned', 'true') == 'true')
|
|
|
|
return add_requested_prefixes(parent.prefix, queryset, show_available, show_assigned)
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&within={instance.prefix}",
|
|
'active_tab': 'prefixes',
|
|
'first_available_prefix': instance.get_first_available_prefix(),
|
|
'show_available': bool(request.GET.get('show_available', 'true') == 'true'),
|
|
'show_assigned': bool(request.GET.get('show_assigned', 'true') == 'true'),
|
|
}
|
|
|
|
|
|
class PrefixIPRangesView(generic.ObjectChildrenView):
|
|
queryset = Prefix.objects.all()
|
|
child_model = IPRange
|
|
table = tables.IPRangeTable
|
|
filterset = filtersets.IPRangeFilterSet
|
|
template_name = 'ipam/prefix/ip_ranges.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_child_ranges().restrict(request.user, 'view').prefetch_related(
|
|
'vrf', 'role', 'tenant', 'tenant__group',
|
|
)
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&parent={instance.prefix}",
|
|
'active_tab': 'ip-ranges',
|
|
'first_available_ip': instance.get_first_available_ip(),
|
|
}
|
|
|
|
|
|
class PrefixIPAddressesView(generic.ObjectChildrenView):
|
|
queryset = Prefix.objects.all()
|
|
child_model = IPAddress
|
|
table = tables.IPAddressTable
|
|
filterset = filtersets.IPAddressFilterSet
|
|
template_name = 'ipam/prefix/ip_addresses.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_child_ips().restrict(request.user, 'view').prefetch_related('vrf', 'tenant')
|
|
|
|
def prep_table_data(self, request, queryset, parent):
|
|
show_available = bool(request.GET.get('show_available', 'true') == 'true')
|
|
if show_available:
|
|
return add_available_ipaddresses(parent.prefix, queryset, parent.is_pool)
|
|
|
|
return queryset
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'bulk_querystring': f"vrf_id={instance.vrf.pk if instance.vrf else '0'}&parent={instance.prefix}",
|
|
'active_tab': 'ip-addresses',
|
|
'first_available_ip': instance.get_first_available_ip(),
|
|
}
|
|
|
|
|
|
class PrefixEditView(generic.ObjectEditView):
|
|
queryset = Prefix.objects.all()
|
|
form = forms.PrefixForm
|
|
|
|
|
|
class PrefixDeleteView(generic.ObjectDeleteView):
|
|
queryset = Prefix.objects.all()
|
|
|
|
|
|
class PrefixBulkImportView(generic.BulkImportView):
|
|
queryset = Prefix.objects.all()
|
|
model_form = forms.PrefixCSVForm
|
|
table = tables.PrefixTable
|
|
|
|
|
|
class PrefixBulkEditView(generic.BulkEditView):
|
|
queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
|
|
filterset = filtersets.PrefixFilterSet
|
|
table = tables.PrefixTable
|
|
form = forms.PrefixBulkEditForm
|
|
|
|
|
|
class PrefixBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role')
|
|
filterset = filtersets.PrefixFilterSet
|
|
table = tables.PrefixTable
|
|
|
|
|
|
#
|
|
# IP Ranges
|
|
#
|
|
|
|
class IPRangeListView(generic.ObjectListView):
|
|
queryset = IPRange.objects.all()
|
|
filterset = filtersets.IPRangeFilterSet
|
|
filterset_form = forms.IPRangeFilterForm
|
|
table = tables.IPRangeTable
|
|
|
|
|
|
class IPRangeView(generic.ObjectView):
|
|
queryset = IPRange.objects.all()
|
|
|
|
|
|
class IPRangeIPAddressesView(generic.ObjectChildrenView):
|
|
queryset = IPRange.objects.all()
|
|
child_model = IPAddress
|
|
table = tables.IPAddressTable
|
|
filterset = filtersets.IPAddressFilterSet
|
|
template_name = 'ipam/iprange/ip_addresses.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_child_ips().restrict(request.user, 'view').prefetch_related(
|
|
'vrf', 'role', 'tenant', 'tenant__group',
|
|
)
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'active_tab': 'ip-addresses',
|
|
}
|
|
|
|
|
|
class IPRangeEditView(generic.ObjectEditView):
|
|
queryset = IPRange.objects.all()
|
|
form = forms.IPRangeForm
|
|
|
|
|
|
class IPRangeDeleteView(generic.ObjectDeleteView):
|
|
queryset = IPRange.objects.all()
|
|
|
|
|
|
class IPRangeBulkImportView(generic.BulkImportView):
|
|
queryset = IPRange.objects.all()
|
|
model_form = forms.IPRangeCSVForm
|
|
table = tables.IPRangeTable
|
|
|
|
|
|
class IPRangeBulkEditView(generic.BulkEditView):
|
|
queryset = IPRange.objects.prefetch_related('vrf', 'tenant')
|
|
filterset = filtersets.IPRangeFilterSet
|
|
table = tables.IPRangeTable
|
|
form = forms.IPRangeBulkEditForm
|
|
|
|
|
|
class IPRangeBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = IPRange.objects.prefetch_related('vrf', 'tenant')
|
|
filterset = filtersets.IPRangeFilterSet
|
|
table = tables.IPRangeTable
|
|
|
|
|
|
#
|
|
# IP addresses
|
|
#
|
|
|
|
class IPAddressListView(generic.ObjectListView):
|
|
queryset = IPAddress.objects.all()
|
|
filterset = filtersets.IPAddressFilterSet
|
|
filterset_form = forms.IPAddressFilterForm
|
|
table = tables.IPAddressTable
|
|
|
|
|
|
class IPAddressView(generic.ObjectView):
|
|
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
|
|
|
|
def get_extra_context(self, request, instance):
|
|
# Parent prefixes table
|
|
parent_prefixes = Prefix.objects.restrict(request.user, 'view').filter(
|
|
vrf=instance.vrf,
|
|
prefix__net_contains_or_equals=str(instance.address.ip)
|
|
).prefetch_related(
|
|
'site', 'role'
|
|
)
|
|
parent_prefixes_table = tables.PrefixTable(
|
|
list(parent_prefixes),
|
|
exclude=('vrf', 'utilization'),
|
|
orderable=False
|
|
)
|
|
|
|
# Duplicate IPs table
|
|
duplicate_ips = IPAddress.objects.restrict(request.user, 'view').filter(
|
|
vrf=instance.vrf,
|
|
address=str(instance.address)
|
|
).exclude(
|
|
pk=instance.pk
|
|
).prefetch_related(
|
|
'nat_inside'
|
|
)
|
|
# Exclude anycast IPs if this IP is anycast
|
|
if instance.role == IPAddressRoleChoices.ROLE_ANYCAST:
|
|
duplicate_ips = duplicate_ips.exclude(role=IPAddressRoleChoices.ROLE_ANYCAST)
|
|
# Limit to a maximum of 10 duplicates displayed here
|
|
duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False)
|
|
|
|
# Related IP table
|
|
related_ips = IPAddress.objects.restrict(request.user, 'view').exclude(
|
|
address=str(instance.address)
|
|
).filter(
|
|
vrf=instance.vrf, address__net_contained_or_equal=str(instance.address)
|
|
)
|
|
related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
|
|
related_ips_table.configure(request)
|
|
|
|
# Find services belonging to the IP
|
|
service_filter = Q(ipaddresses=instance)
|
|
|
|
# Find services listening on all IPs on the assigned device/vm
|
|
try:
|
|
if instance.assigned_object and instance.assigned_object.parent_object:
|
|
parent_object = instance.assigned_object.parent_object
|
|
|
|
if isinstance(parent_object, VirtualMachine):
|
|
service_filter |= (Q(virtual_machine=parent_object) & Q(ipaddresses=None))
|
|
elif isinstance(parent_object, Device):
|
|
service_filter |= (Q(device=parent_object) & Q(ipaddresses=None))
|
|
except AttributeError:
|
|
pass
|
|
|
|
services = Service.objects.restrict(request.user, 'view').filter(service_filter)
|
|
|
|
return {
|
|
'parent_prefixes_table': parent_prefixes_table,
|
|
'duplicate_ips_table': duplicate_ips_table,
|
|
'more_duplicate_ips': duplicate_ips.count() > 10,
|
|
'related_ips_table': related_ips_table,
|
|
'services': services,
|
|
}
|
|
|
|
|
|
class IPAddressEditView(generic.ObjectEditView):
|
|
queryset = IPAddress.objects.all()
|
|
form = forms.IPAddressForm
|
|
template_name = 'ipam/ipaddress_edit.html'
|
|
|
|
def alter_object(self, obj, request, url_args, url_kwargs):
|
|
|
|
if 'interface' in request.GET:
|
|
try:
|
|
obj.assigned_object = Interface.objects.get(pk=request.GET['interface'])
|
|
except (ValueError, Interface.DoesNotExist):
|
|
pass
|
|
|
|
elif 'vminterface' in request.GET:
|
|
try:
|
|
obj.assigned_object = VMInterface.objects.get(pk=request.GET['vminterface'])
|
|
except (ValueError, VMInterface.DoesNotExist):
|
|
pass
|
|
|
|
elif 'fhrpgroup' in request.GET:
|
|
try:
|
|
obj.assigned_object = FHRPGroup.objects.get(pk=request.GET['fhrpgroup'])
|
|
except (ValueError, FHRPGroup.DoesNotExist):
|
|
pass
|
|
|
|
return obj
|
|
|
|
|
|
# TODO: Standardize or remove this view
|
|
class IPAddressAssignView(generic.ObjectView):
|
|
"""
|
|
Search for IPAddresses to be assigned to an Interface.
|
|
"""
|
|
queryset = IPAddress.objects.all()
|
|
|
|
def dispatch(self, request, *args, **kwargs):
|
|
|
|
# Redirect user if an interface has not been provided
|
|
if 'interface' not in request.GET and 'vminterface' not in request.GET:
|
|
return redirect('ipam:ipaddress_add')
|
|
|
|
return super().dispatch(request, *args, **kwargs)
|
|
|
|
def get(self, request):
|
|
form = forms.IPAddressAssignForm()
|
|
|
|
return render(request, 'ipam/ipaddress_assign.html', {
|
|
'form': form,
|
|
'return_url': request.GET.get('return_url', ''),
|
|
})
|
|
|
|
def post(self, request):
|
|
form = forms.IPAddressAssignForm(request.POST)
|
|
table = None
|
|
|
|
if form.is_valid():
|
|
|
|
addresses = self.queryset.prefetch_related('vrf', 'tenant')
|
|
# Limit to 100 results
|
|
addresses = filtersets.IPAddressFilterSet(request.POST, addresses).qs[:100]
|
|
table = tables.IPAddressAssignTable(addresses)
|
|
|
|
return render(request, 'ipam/ipaddress_assign.html', {
|
|
'form': form,
|
|
'table': table,
|
|
'return_url': request.GET.get('return_url'),
|
|
})
|
|
|
|
|
|
class IPAddressDeleteView(generic.ObjectDeleteView):
|
|
queryset = IPAddress.objects.all()
|
|
|
|
|
|
class IPAddressBulkCreateView(generic.BulkCreateView):
|
|
queryset = IPAddress.objects.all()
|
|
form = forms.IPAddressBulkCreateForm
|
|
model_form = forms.IPAddressBulkAddForm
|
|
pattern_target = 'address'
|
|
template_name = 'ipam/ipaddress_bulk_add.html'
|
|
|
|
|
|
class IPAddressBulkImportView(generic.BulkImportView):
|
|
queryset = IPAddress.objects.all()
|
|
model_form = forms.IPAddressCSVForm
|
|
table = tables.IPAddressTable
|
|
|
|
|
|
class IPAddressBulkEditView(generic.BulkEditView):
|
|
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
|
|
filterset = filtersets.IPAddressFilterSet
|
|
table = tables.IPAddressTable
|
|
form = forms.IPAddressBulkEditForm
|
|
|
|
|
|
class IPAddressBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
|
|
filterset = filtersets.IPAddressFilterSet
|
|
table = tables.IPAddressTable
|
|
|
|
|
|
#
|
|
# VLAN groups
|
|
#
|
|
|
|
class VLANGroupListView(generic.ObjectListView):
|
|
queryset = VLANGroup.objects.annotate(
|
|
vlan_count=count_related(VLAN, 'group')
|
|
)
|
|
filterset = filtersets.VLANGroupFilterSet
|
|
filterset_form = forms.VLANGroupFilterForm
|
|
table = tables.VLANGroupTable
|
|
|
|
|
|
class VLANGroupView(generic.ObjectView):
|
|
queryset = VLANGroup.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
vlans = VLAN.objects.restrict(request.user, 'view').filter(group=instance).prefetch_related(
|
|
Prefetch('prefixes', queryset=Prefix.objects.restrict(request.user))
|
|
).order_by('vid')
|
|
vlans_count = vlans.count()
|
|
vlans = add_available_vlans(vlans, vlan_group=instance)
|
|
|
|
vlans_table = tables.VLANTable(vlans, user=request.user, exclude=('group',))
|
|
if request.user.has_perm('ipam.change_vlan') or request.user.has_perm('ipam.delete_vlan'):
|
|
vlans_table.columns.show('pk')
|
|
vlans_table.configure(request)
|
|
|
|
# Compile permissions list for rendering the object table
|
|
permissions = {
|
|
'add': request.user.has_perm('ipam.add_vlan'),
|
|
'change': request.user.has_perm('ipam.change_vlan'),
|
|
'delete': request.user.has_perm('ipam.delete_vlan'),
|
|
}
|
|
|
|
return {
|
|
'vlans_count': vlans_count,
|
|
'vlans_table': vlans_table,
|
|
'permissions': permissions,
|
|
}
|
|
|
|
|
|
class VLANGroupEditView(generic.ObjectEditView):
|
|
queryset = VLANGroup.objects.all()
|
|
form = forms.VLANGroupForm
|
|
|
|
|
|
class VLANGroupDeleteView(generic.ObjectDeleteView):
|
|
queryset = VLANGroup.objects.all()
|
|
|
|
|
|
class VLANGroupBulkImportView(generic.BulkImportView):
|
|
queryset = VLANGroup.objects.all()
|
|
model_form = forms.VLANGroupCSVForm
|
|
table = tables.VLANGroupTable
|
|
|
|
|
|
class VLANGroupBulkEditView(generic.BulkEditView):
|
|
queryset = VLANGroup.objects.annotate(
|
|
vlan_count=count_related(VLAN, 'group')
|
|
)
|
|
filterset = filtersets.VLANGroupFilterSet
|
|
table = tables.VLANGroupTable
|
|
form = forms.VLANGroupBulkEditForm
|
|
|
|
|
|
class VLANGroupBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = VLANGroup.objects.annotate(
|
|
vlan_count=count_related(VLAN, 'group')
|
|
)
|
|
filterset = filtersets.VLANGroupFilterSet
|
|
table = tables.VLANGroupTable
|
|
|
|
|
|
#
|
|
# FHRP groups
|
|
#
|
|
|
|
class FHRPGroupListView(generic.ObjectListView):
|
|
queryset = FHRPGroup.objects.annotate(
|
|
member_count=count_related(FHRPGroupAssignment, 'group')
|
|
)
|
|
filterset = filtersets.FHRPGroupFilterSet
|
|
filterset_form = forms.FHRPGroupFilterForm
|
|
table = tables.FHRPGroupTable
|
|
|
|
|
|
class FHRPGroupView(generic.ObjectView):
|
|
queryset = FHRPGroup.objects.all()
|
|
|
|
def get_extra_context(self, request, instance):
|
|
# Get assigned IP addresses
|
|
ipaddress_table = tables.AssignedIPAddressesTable(
|
|
data=instance.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'),
|
|
orderable=False
|
|
)
|
|
|
|
# Get assigned interfaces
|
|
members_table = tables.FHRPGroupAssignmentTable(
|
|
data=FHRPGroupAssignment.objects.restrict(request.user, 'view').filter(group=instance),
|
|
orderable=False
|
|
)
|
|
members_table.columns.hide('group')
|
|
|
|
return {
|
|
'ipaddress_table': ipaddress_table,
|
|
'members_table': members_table,
|
|
'member_count': FHRPGroupAssignment.objects.filter(group=instance).count(),
|
|
}
|
|
|
|
|
|
class FHRPGroupEditView(generic.ObjectEditView):
|
|
queryset = FHRPGroup.objects.all()
|
|
form = forms.FHRPGroupForm
|
|
template_name = 'ipam/fhrpgroup_edit.html'
|
|
|
|
def get_return_url(self, request, obj=None):
|
|
return_url = super().get_return_url(request, obj)
|
|
|
|
# If we're redirecting the user to the FHRPGroupAssignment creation form,
|
|
# initialize the group field with the FHRPGroup we just saved.
|
|
if return_url.startswith(reverse('ipam:fhrpgroupassignment_add')):
|
|
return_url += f'&group={obj.pk}'
|
|
|
|
return return_url
|
|
|
|
|
|
class FHRPGroupDeleteView(generic.ObjectDeleteView):
|
|
queryset = FHRPGroup.objects.all()
|
|
|
|
|
|
class FHRPGroupBulkImportView(generic.BulkImportView):
|
|
queryset = FHRPGroup.objects.all()
|
|
model_form = forms.FHRPGroupCSVForm
|
|
table = tables.FHRPGroupTable
|
|
|
|
|
|
class FHRPGroupBulkEditView(generic.BulkEditView):
|
|
queryset = FHRPGroup.objects.all()
|
|
filterset = filtersets.FHRPGroupFilterSet
|
|
table = tables.FHRPGroupTable
|
|
form = forms.FHRPGroupBulkEditForm
|
|
|
|
|
|
class FHRPGroupBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = FHRPGroup.objects.all()
|
|
filterset = filtersets.FHRPGroupFilterSet
|
|
table = tables.FHRPGroupTable
|
|
|
|
|
|
#
|
|
# FHRP group assignments
|
|
#
|
|
|
|
class FHRPGroupAssignmentEditView(generic.ObjectEditView):
|
|
queryset = FHRPGroupAssignment.objects.all()
|
|
form = forms.FHRPGroupAssignmentForm
|
|
template_name = 'ipam/fhrpgroupassignment_edit.html'
|
|
|
|
def alter_object(self, instance, request, args, kwargs):
|
|
if not instance.pk:
|
|
# Assign the interface based on URL kwargs
|
|
content_type = get_object_or_404(ContentType, pk=request.GET.get('interface_type'))
|
|
instance.interface = get_object_or_404(content_type.model_class(), pk=request.GET.get('interface_id'))
|
|
return instance
|
|
|
|
|
|
class FHRPGroupAssignmentDeleteView(generic.ObjectDeleteView):
|
|
queryset = FHRPGroupAssignment.objects.all()
|
|
|
|
|
|
#
|
|
# VLANs
|
|
#
|
|
|
|
class VLANListView(generic.ObjectListView):
|
|
queryset = VLAN.objects.all()
|
|
filterset = filtersets.VLANFilterSet
|
|
filterset_form = forms.VLANFilterForm
|
|
table = tables.VLANTable
|
|
|
|
|
|
class VLANView(generic.ObjectView):
|
|
queryset = VLAN.objects.prefetch_related('site__region', 'tenant__group', 'role')
|
|
|
|
def get_extra_context(self, request, instance):
|
|
prefixes = Prefix.objects.restrict(request.user, 'view').filter(vlan=instance).prefetch_related(
|
|
'vrf', 'site', 'role'
|
|
)
|
|
prefix_table = tables.PrefixTable(list(prefixes), exclude=('vlan', 'utilization'), orderable=False)
|
|
|
|
return {
|
|
'prefix_table': prefix_table,
|
|
}
|
|
|
|
|
|
class VLANInterfacesView(generic.ObjectChildrenView):
|
|
queryset = VLAN.objects.all()
|
|
child_model = Interface
|
|
table = tables.VLANDevicesTable
|
|
filterset = InterfaceFilterSet
|
|
template_name = 'ipam/vlan/interfaces.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_interfaces().restrict(request.user, 'view')
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'active_tab': 'interfaces',
|
|
}
|
|
|
|
|
|
class VLANVMInterfacesView(generic.ObjectChildrenView):
|
|
queryset = VLAN.objects.all()
|
|
child_model = VMInterface
|
|
table = tables.VLANVirtualMachinesTable
|
|
filterset = VMInterfaceFilterSet
|
|
template_name = 'ipam/vlan/vminterfaces.html'
|
|
|
|
def get_children(self, request, parent):
|
|
return parent.get_vminterfaces().restrict(request.user, 'view')
|
|
|
|
def get_extra_context(self, request, instance):
|
|
return {
|
|
'active_tab': 'vminterfaces',
|
|
}
|
|
|
|
|
|
class VLANEditView(generic.ObjectEditView):
|
|
queryset = VLAN.objects.all()
|
|
form = forms.VLANForm
|
|
template_name = 'ipam/vlan_edit.html'
|
|
|
|
|
|
class VLANDeleteView(generic.ObjectDeleteView):
|
|
queryset = VLAN.objects.all()
|
|
|
|
|
|
class VLANBulkImportView(generic.BulkImportView):
|
|
queryset = VLAN.objects.all()
|
|
model_form = forms.VLANCSVForm
|
|
table = tables.VLANTable
|
|
|
|
|
|
class VLANBulkEditView(generic.BulkEditView):
|
|
queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role')
|
|
filterset = filtersets.VLANFilterSet
|
|
table = tables.VLANTable
|
|
form = forms.VLANBulkEditForm
|
|
|
|
|
|
class VLANBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role')
|
|
filterset = filtersets.VLANFilterSet
|
|
table = tables.VLANTable
|
|
|
|
|
|
#
|
|
# Service templates
|
|
#
|
|
|
|
class ServiceTemplateListView(generic.ObjectListView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
filterset = filtersets.ServiceTemplateFilterSet
|
|
filterset_form = forms.ServiceTemplateFilterForm
|
|
table = tables.ServiceTemplateTable
|
|
|
|
|
|
class ServiceTemplateView(generic.ObjectView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
|
|
|
|
class ServiceTemplateEditView(generic.ObjectEditView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
form = forms.ServiceTemplateForm
|
|
|
|
|
|
class ServiceTemplateDeleteView(generic.ObjectDeleteView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
|
|
|
|
class ServiceTemplateBulkImportView(generic.BulkImportView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
model_form = forms.ServiceTemplateCSVForm
|
|
table = tables.ServiceTemplateTable
|
|
|
|
|
|
class ServiceTemplateBulkEditView(generic.BulkEditView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
filterset = filtersets.ServiceTemplateFilterSet
|
|
table = tables.ServiceTemplateTable
|
|
form = forms.ServiceTemplateBulkEditForm
|
|
|
|
|
|
class ServiceTemplateBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = ServiceTemplate.objects.all()
|
|
filterset = filtersets.ServiceTemplateFilterSet
|
|
table = tables.ServiceTemplateTable
|
|
|
|
|
|
#
|
|
# Services
|
|
#
|
|
|
|
class ServiceListView(generic.ObjectListView):
|
|
queryset = Service.objects.all()
|
|
filterset = filtersets.ServiceFilterSet
|
|
filterset_form = forms.ServiceFilterForm
|
|
table = tables.ServiceTable
|
|
|
|
|
|
class ServiceView(generic.ObjectView):
|
|
queryset = Service.objects.prefetch_related('ipaddresses')
|
|
|
|
|
|
class ServiceCreateView(generic.ObjectEditView):
|
|
queryset = Service.objects.all()
|
|
form = forms.ServiceCreateForm
|
|
template_name = 'ipam/service_create.html'
|
|
|
|
|
|
class ServiceEditView(generic.ObjectEditView):
|
|
queryset = Service.objects.prefetch_related('ipaddresses')
|
|
form = forms.ServiceForm
|
|
template_name = 'ipam/service_edit.html'
|
|
|
|
|
|
class ServiceDeleteView(generic.ObjectDeleteView):
|
|
queryset = Service.objects.all()
|
|
|
|
|
|
class ServiceBulkImportView(generic.BulkImportView):
|
|
queryset = Service.objects.all()
|
|
model_form = forms.ServiceCSVForm
|
|
table = tables.ServiceTable
|
|
|
|
|
|
class ServiceBulkEditView(generic.BulkEditView):
|
|
queryset = Service.objects.prefetch_related('device', 'virtual_machine')
|
|
filterset = filtersets.ServiceFilterSet
|
|
table = tables.ServiceTable
|
|
form = forms.ServiceBulkEditForm
|
|
|
|
|
|
class ServiceBulkDeleteView(generic.BulkDeleteView):
|
|
queryset = Service.objects.prefetch_related('device', 'virtual_machine')
|
|
filterset = filtersets.ServiceFilterSet
|
|
table = tables.ServiceTable
|