1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00
Files
netbox-community-netbox/netbox/netbox/views.py

328 lines
12 KiB
Python

from collections import OrderedDict
from django.conf import settings
from django.db.models import Count, F
from django.shortcuts import render
from django.views.generic import View
from packaging import version
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.views import APIView
from circuits.filters import CircuitFilterSet, ProviderFilterSet
from circuits.models import Circuit, Provider
from circuits.tables import CircuitTable, ProviderTable
from dcim.filters import (
CableFilterSet, DeviceFilterSet, DeviceTypeFilterSet, PowerFeedFilterSet, RackFilterSet, RackGroupFilterSet,
SiteFilterSet, VirtualChassisFilterSet,
)
from dcim.models import (
Cable, ConsolePort, Device, DeviceType, Interface, PowerPanel, PowerFeed, PowerPort, Rack, RackGroup, Site,
VirtualChassis,
)
from dcim.tables import (
CableTable, DeviceTable, DeviceTypeTable, PowerFeedTable, RackTable, RackGroupTable, SiteTable,
VirtualChassisTable,
)
from extras.models import ObjectChange, JobResult
from ipam.filters import AggregateFilterSet, IPAddressFilterSet, PrefixFilterSet, VLANFilterSet, VRFFilterSet
from ipam.models import Aggregate, IPAddress, Prefix, VLAN, VRF
from ipam.tables import AggregateTable, IPAddressTable, PrefixTable, VLANTable, VRFTable
from netbox.releases import get_latest_release
from secrets.filters import SecretFilterSet
from secrets.models import Secret
from secrets.tables import SecretTable
from tenancy.filters import TenantFilterSet
from tenancy.models import Tenant
from tenancy.tables import TenantTable
from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet
from virtualization.models import Cluster, VirtualMachine
from virtualization.tables import ClusterTable, VirtualMachineDetailTable
from .forms import SearchForm
SEARCH_MAX_RESULTS = 15
SEARCH_TYPES = OrderedDict((
# Circuits
('provider', {
'queryset': Provider.objects.annotate(count_circuits=Count('circuits')),
'filterset': ProviderFilterSet,
'table': ProviderTable,
'url': 'circuits:provider_list',
}),
('circuit', {
'queryset': Circuit.objects.prefetch_related(
'type', 'provider', 'tenant', 'terminations__site'
).annotate_sites(),
'filterset': CircuitFilterSet,
'table': CircuitTable,
'url': 'circuits:circuit_list',
}),
# DCIM
('site', {
'queryset': Site.objects.prefetch_related('region', 'tenant'),
'filterset': SiteFilterSet,
'table': SiteTable,
'url': 'dcim:site_list',
}),
('rack', {
'queryset': Rack.objects.prefetch_related('site', 'group', 'tenant', 'role'),
'filterset': RackFilterSet,
'table': RackTable,
'url': 'dcim:rack_list',
}),
('rackgroup', {
'queryset': RackGroup.objects.prefetch_related('site').annotate(rack_count=Count('racks')),
'filterset': RackGroupFilterSet,
'table': RackGroupTable,
'url': 'dcim:rackgroup_list',
}),
('devicetype', {
'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances')),
'filterset': DeviceTypeFilterSet,
'table': DeviceTypeTable,
'url': 'dcim:devicetype_list',
}),
('device', {
'queryset': Device.objects.prefetch_related(
'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6',
),
'filterset': DeviceFilterSet,
'table': DeviceTable,
'url': 'dcim:device_list',
}),
('virtualchassis', {
'queryset': VirtualChassis.objects.prefetch_related('master').annotate(member_count=Count('members')),
'filterset': VirtualChassisFilterSet,
'table': VirtualChassisTable,
'url': 'dcim:virtualchassis_list',
}),
('cable', {
'queryset': Cable.objects.all(),
'filterset': CableFilterSet,
'table': CableTable,
'url': 'dcim:cable_list',
}),
('powerfeed', {
'queryset': PowerFeed.objects.all(),
'filterset': PowerFeedFilterSet,
'table': PowerFeedTable,
'url': 'dcim:powerfeed_list',
}),
# Virtualization
('cluster', {
'queryset': Cluster.objects.prefetch_related('type', 'group'),
'filterset': ClusterFilterSet,
'table': ClusterTable,
'url': 'virtualization:cluster_list',
}),
('virtualmachine', {
'queryset': VirtualMachine.objects.prefetch_related(
'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6',
),
'filterset': VirtualMachineFilterSet,
'table': VirtualMachineDetailTable,
'url': 'virtualization:virtualmachine_list',
}),
# IPAM
('vrf', {
'queryset': VRF.objects.prefetch_related('tenant'),
'filterset': VRFFilterSet,
'table': VRFTable,
'url': 'ipam:vrf_list',
}),
('aggregate', {
'queryset': Aggregate.objects.prefetch_related('rir'),
'filterset': AggregateFilterSet,
'table': AggregateTable,
'url': 'ipam:aggregate_list',
}),
('prefix', {
'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'),
'filterset': PrefixFilterSet,
'table': PrefixTable,
'url': 'ipam:prefix_list',
}),
('ipaddress', {
'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant'),
'filterset': IPAddressFilterSet,
'table': IPAddressTable,
'url': 'ipam:ipaddress_list',
}),
('vlan', {
'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role'),
'filterset': VLANFilterSet,
'table': VLANTable,
'url': 'ipam:vlan_list',
}),
# Secrets
('secret', {
'queryset': Secret.objects.prefetch_related('role', 'device'),
'filterset': SecretFilterSet,
'table': SecretTable,
'url': 'secrets:secret_list',
}),
# Tenancy
('tenant', {
'queryset': Tenant.objects.prefetch_related('group'),
'filterset': TenantFilterSet,
'table': TenantTable,
'url': 'tenancy:tenant_list',
}),
))
class HomeView(View):
template_name = 'home.html'
def get(self, request):
connected_consoleports = ConsolePort.objects.restrict(request.user, 'view').filter(
connected_endpoint__isnull=False
)
connected_powerports = PowerPort.objects.restrict(request.user, 'view').filter(
_connected_poweroutlet__isnull=False
)
connected_interfaces = Interface.objects.restrict(request.user, 'view').filter(
_connected_interface__isnull=False,
pk__lt=F('_connected_interface')
)
stats = {
# Organization
'site_count': Site.objects.restrict(request.user, 'view').count(),
'tenant_count': Tenant.objects.restrict(request.user, 'view').count(),
# DCIM
'rack_count': Rack.objects.restrict(request.user, 'view').count(),
'devicetype_count': DeviceType.objects.restrict(request.user, 'view').count(),
'device_count': Device.objects.restrict(request.user, 'view').count(),
'interface_connections_count': connected_interfaces.count(),
'cable_count': Cable.objects.restrict(request.user, 'view').count(),
'console_connections_count': connected_consoleports.count(),
'power_connections_count': connected_powerports.count(),
'powerpanel_count': PowerPanel.objects.restrict(request.user, 'view').count(),
'powerfeed_count': PowerFeed.objects.restrict(request.user, 'view').count(),
# IPAM
'vrf_count': VRF.objects.restrict(request.user, 'view').count(),
'aggregate_count': Aggregate.objects.restrict(request.user, 'view').count(),
'prefix_count': Prefix.objects.restrict(request.user, 'view').count(),
'ipaddress_count': IPAddress.objects.restrict(request.user, 'view').count(),
'vlan_count': VLAN.objects.restrict(request.user, 'view').count(),
# Circuits
'provider_count': Provider.objects.restrict(request.user, 'view').count(),
'circuit_count': Circuit.objects.restrict(request.user, 'view').count(),
# Secrets
'secret_count': Secret.objects.restrict(request.user, 'view').count(),
# Virtualization
'cluster_count': Cluster.objects.restrict(request.user, 'view').count(),
'virtualmachine_count': VirtualMachine.objects.restrict(request.user, 'view').count(),
}
changelog = ObjectChange.objects.restrict(request.user, 'view').prefetch_related('user', 'changed_object_type')
# Check whether a new release is available. (Only for staff/superusers.)
new_release = None
if request.user.is_staff or request.user.is_superuser:
latest_release, release_url = get_latest_release()
if isinstance(latest_release, version.Version):
current_version = version.parse(settings.VERSION)
if latest_release > current_version:
new_release = {
'version': str(latest_release),
'url': release_url,
}
return render(request, self.template_name, {
'search_form': SearchForm(),
'stats': stats,
'report_results': [],#ReportResult.objects.order_by('-created')[:10],
'changelog': changelog[:15],
'new_release': new_release,
})
class SearchView(View):
def get(self, request):
# No query
if 'q' not in request.GET:
return render(request, 'search.html', {
'form': SearchForm(),
})
form = SearchForm(request.GET)
results = []
if form.is_valid():
if form.cleaned_data['obj_type']:
# Searching for a single type of object
obj_types = [form.cleaned_data['obj_type']]
else:
# Searching all object types
obj_types = SEARCH_TYPES.keys()
for obj_type in obj_types:
queryset = SEARCH_TYPES[obj_type]['queryset'].restrict(request.user, 'view')
filterset = SEARCH_TYPES[obj_type]['filterset']
table = SEARCH_TYPES[obj_type]['table']
url = SEARCH_TYPES[obj_type]['url']
# Construct the results table for this object type
filtered_queryset = filterset({'q': form.cleaned_data['q']}, queryset=queryset).qs
table = table(filtered_queryset, orderable=False)
table.paginate(per_page=SEARCH_MAX_RESULTS)
if table.page:
results.append({
'name': queryset.model._meta.verbose_name_plural,
'table': table,
'url': '{}?q={}'.format(reverse(url), form.cleaned_data['q'])
})
return render(request, 'search.html', {
'form': form,
'results': results,
})
class StaticMediaFailureView(View):
"""
Display a user-friendly error message with troubleshooting tips when a static media file fails to load.
"""
def get(self, request):
return render(request, 'media_failure.html', {
'filename': request.GET.get('filename')
})
class APIRootView(APIView):
_ignore_model_permissions = True
exclude_from_schema = True
swagger_schema = None
def get_view_name(self):
return "API Root"
def get(self, request, format=None):
return Response(OrderedDict((
('circuits', reverse('circuits-api:api-root', request=request, format=format)),
('dcim', reverse('dcim-api:api-root', request=request, format=format)),
('extras', reverse('extras-api:api-root', request=request, format=format)),
('ipam', reverse('ipam-api:api-root', request=request, format=format)),
('plugins', reverse('plugins-api:api-root', request=request, format=format)),
('secrets', reverse('secrets-api:api-root', request=request, format=format)),
('tenancy', reverse('tenancy-api:api-root', request=request, format=format)),
('users', reverse('users-api:api-root', request=request, format=format)),
('virtualization', reverse('virtualization-api:api-root', request=request, format=format)),
)))