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/dcim/views.py

2460 lines
75 KiB
Python
Raw Normal View History

from collections import OrderedDict
from django.conf import settings
2016-03-01 11:23:03 -05:00
from django.contrib import messages
2019-03-21 17:47:43 -04:00
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import EmptyPage, PageNotAnInteger
from django.db import transaction
from django.db.models import Count, F, Prefetch
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory
2016-03-01 11:23:03 -05:00
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.views.generic import View
2016-03-01 11:23:03 -05:00
from circuits.models import Circuit
2019-09-20 08:35:14 -04:00
from extras.models import Graph
from extras.views import ObjectConfigContextView
from ipam.models import IPAddress, Prefix, Service, VLAN
2018-07-11 15:30:54 -04:00
from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
2020-06-01 11:43:49 -04:00
from secrets.models import Secret
2016-03-01 11:23:03 -05:00
from utilities.forms import ConfirmationForm
from utilities.paginator import EnhancedPaginator
from utilities.permissions import get_permission_for_model
from utilities.utils import csv_format
2016-05-18 16:02:53 -04:00
from utilities.views import (
BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, BulkRenameView, ComponentCreateView,
GetReturnURLMixin, ObjectView, ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
ObjectPermissionRequiredMixin,
2016-05-18 16:02:53 -04:00
)
from virtualization.models import VirtualMachine
2016-05-18 16:02:53 -04:00
from . import filters, forms, tables
from .choices import DeviceFaceChoices
from .constants import NONCONNECTABLE_IFACE_TYPES
2016-05-18 16:02:53 -04:00
from .models import (
Cable, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, FrontPort, FrontPortTemplate, Interface, InterfaceTemplate,
2019-03-11 22:40:52 -04:00
InventoryItem, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerOutletTemplate, PowerPanel, PowerPort,
PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RearPort, RearPortTemplate, Region, Site,
VirtualChassis,
2016-05-18 16:02:53 -04:00
)
2016-03-01 11:23:03 -05:00
2020-05-21 16:34:15 -04:00
class BulkDisconnectView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
"""
An extendable view for disconnection console/power/interface components in bulk.
"""
queryset = None
template_name = 'dcim/bulk_disconnect.html'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Create a new Form class from ConfirmationForm
class _Form(ConfirmationForm):
pk = ModelMultipleChoiceField(
queryset=self.queryset,
widget=MultipleHiddenInput()
)
self.form = _Form
def get_required_permission(self):
return get_permission_for_model(self.queryset.model, 'change')
def post(self, request):
selected_objects = []
return_url = self.get_return_url(request)
if '_confirm' in request.POST:
form = self.form(request.POST)
if form.is_valid():
with transaction.atomic():
count = 0
for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']):
if obj.cable is None:
continue
obj.cable.delete()
count += 1
messages.success(request, "Disconnected {} {}".format(
count, self.queryset.model._meta.verbose_name_plural
))
return redirect(return_url)
else:
form = self.form(initial={'pk': request.POST.getlist('pk')})
selected_objects = self.queryset.filter(pk__in=form.initial['pk'])
return render(request, self.template_name, {
'form': form,
'obj_type_plural': self.queryset.model._meta.verbose_name_plural,
'selected_objects': selected_objects,
'return_url': return_url,
})
2017-02-28 12:11:43 -05:00
#
# Regions
#
class RegionListView(ObjectListView):
queryset = Region.objects.add_related_count(
Region.objects.all(),
Site,
'region',
'site_count',
cumulative=True
)
filterset = filters.RegionFilterSet
filterset_form = forms.RegionFilterForm
2017-02-28 12:11:43 -05:00
table = tables.RegionTable
class RegionEditView(ObjectEditView):
queryset = Region.objects.all()
model_form = forms.RegionForm
2017-02-28 12:11:43 -05:00
class RegionDeleteView(ObjectDeleteView):
queryset = Region.objects.all()
class RegionBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Region.objects.all()
2017-07-18 01:50:26 +03:00
model_form = forms.RegionCSVForm
table = tables.RegionTable
class RegionBulkDeleteView(BulkDeleteView):
queryset = Region.objects.all()
filterset = filters.RegionFilterSet
table = tables.RegionTable
2017-02-28 12:11:43 -05:00
2016-03-01 11:23:03 -05:00
#
# Sites
#
class SiteListView(ObjectListView):
queryset = Site.objects.prefetch_related('region', 'tenant')
filterset = filters.SiteFilterSet
filterset_form = forms.SiteFilterForm
table = tables.SiteTable
2016-03-01 11:23:03 -05:00
class SiteView(ObjectView):
2020-05-11 14:32:10 -04:00
queryset = Site.objects.prefetch_related('region', 'tenant__group')
def get(self, request, slug):
2020-05-11 14:32:10 -04:00
site = get_object_or_404(self.queryset, slug=slug)
stats = {
2020-06-01 11:43:49 -04:00
'rack_count': Rack.objects.restrict(request.user, 'view').filter(site=site).count(),
'device_count': Device.objects.restrict(request.user, 'view').filter(site=site).count(),
'prefix_count': Prefix.objects.restrict(request.user, 'view').filter(site=site).count(),
'vlan_count': VLAN.objects.restrict(request.user, 'view').filter(site=site).count(),
'circuit_count': Circuit.objects.restrict(request.user, 'view').filter(terminations__site=site).count(),
'vm_count': VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=site).count(),
}
2020-06-01 11:43:49 -04:00
rack_groups = RackGroup.objects.restrict(request.user, 'view').filter(site=site).annotate(
rack_count=Count('racks')
)
show_graphs = Graph.objects.filter(type__model='site').exists()
return render(request, 'dcim/site.html', {
'site': site,
'stats': stats,
'rack_groups': rack_groups,
'show_graphs': show_graphs,
})
2016-03-01 11:23:03 -05:00
class SiteEditView(ObjectEditView):
queryset = Site.objects.all()
model_form = forms.SiteForm
template_name = 'dcim/site_edit.html'
2016-03-01 11:23:03 -05:00
class SiteDeleteView(ObjectDeleteView):
queryset = Site.objects.all()
2016-03-01 11:23:03 -05:00
class SiteBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Site.objects.all()
model_form = forms.SiteCSVForm
2016-05-18 16:02:53 -04:00
table = tables.SiteTable
2016-03-01 11:23:03 -05:00
class SiteBulkEditView(BulkEditView):
queryset = Site.objects.prefetch_related('region', 'tenant')
filterset = filters.SiteFilterSet
table = tables.SiteTable
2016-07-28 15:30:29 -04:00
form = forms.SiteBulkEditForm
class SiteBulkDeleteView(BulkDeleteView):
queryset = Site.objects.prefetch_related('region', 'tenant')
filterset = filters.SiteFilterSet
table = tables.SiteTable
2016-03-30 12:26:37 -04:00
#
# Rack groups
#
class RackGroupListView(ObjectListView):
2020-03-11 14:40:29 -04:00
queryset = RackGroup.objects.add_related_count(
RackGroup.objects.all(),
Rack,
'group',
'rack_count',
cumulative=True
).prefetch_related('site')
filterset = filters.RackGroupFilterSet
filterset_form = forms.RackGroupFilterForm
2016-05-18 16:02:53 -04:00
table = tables.RackGroupTable
2016-03-30 12:26:37 -04:00
class RackGroupEditView(ObjectEditView):
queryset = RackGroup.objects.all()
model_form = forms.RackGroupForm
2016-03-30 12:26:37 -04:00
class RackGroupDeleteView(ObjectDeleteView):
queryset = RackGroup.objects.all()
class RackGroupBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = RackGroup.objects.all()
model_form = forms.RackGroupCSVForm
table = tables.RackGroupTable
class RackGroupBulkDeleteView(BulkDeleteView):
queryset = RackGroup.objects.prefetch_related('site').annotate(rack_count=Count('racks'))
filterset = filters.RackGroupFilterSet
table = tables.RackGroupTable
2016-03-30 12:26:37 -04:00
2016-08-10 11:52:27 -04:00
#
# Rack roles
#
class RackRoleListView(ObjectListView):
2016-08-10 11:52:27 -04:00
queryset = RackRole.objects.annotate(rack_count=Count('racks'))
table = tables.RackRoleTable
class RackRoleEditView(ObjectEditView):
queryset = RackRole.objects.all()
model_form = forms.RackRoleForm
2016-08-10 11:52:27 -04:00
class RackRoleDeleteView(ObjectDeleteView):
queryset = RackRole.objects.all()
class RackRoleBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = RackRole.objects.all()
model_form = forms.RackRoleCSVForm
table = tables.RackRoleTable
class RackRoleBulkDeleteView(BulkDeleteView):
queryset = RackRole.objects.annotate(rack_count=Count('racks'))
table = tables.RackRoleTable
2016-08-10 11:52:27 -04:00
2016-03-01 11:23:03 -05:00
#
# Racks
#
class RackListView(ObjectListView):
queryset = Rack.objects.prefetch_related(
'site', 'group', 'tenant', 'role', 'devices__device_type'
).annotate(
device_count=Count('devices')
)
filterset = filters.RackFilterSet
filterset_form = forms.RackFilterForm
table = tables.RackDetailTable
2016-03-01 11:23:03 -05:00
class RackElevationListView(ObjectListView):
"""
Display a set of rack elevations side-by-side.
"""
queryset = Rack.objects.prefetch_related('role')
def get(self, request):
racks = filters.RackFilterSet(request.GET, self.queryset).qs
total_count = racks.count()
# Pagination
per_page = request.GET.get('per_page', settings.PAGINATE_COUNT)
page_number = request.GET.get('page', 1)
paginator = EnhancedPaginator(racks, per_page)
try:
page = paginator.page(page_number)
except PageNotAnInteger:
page = paginator.page(1)
except EmptyPage:
page = paginator.page(paginator.num_pages)
# Determine rack face
rack_face = request.GET.get('face', DeviceFaceChoices.FACE_FRONT)
if rack_face not in DeviceFaceChoices.values():
rack_face = DeviceFaceChoices.FACE_FRONT
return render(request, 'dcim/rack_elevation_list.html', {
'paginator': paginator,
'page': page,
'total_count': total_count,
'rack_face': rack_face,
'filter_form': forms.RackElevationFilterForm(request.GET),
})
class RackView(ObjectView):
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'group', 'role')
2016-03-01 11:23:03 -05:00
def get(self, request, pk):
rack = get_object_or_404(self.queryset, pk=pk)
2020-06-01 11:43:49 -04:00
nonracked_devices = Device.objects.restrict(request.user, 'view').filter(
rack=rack,
position__isnull=True,
parent_bay__isnull=True
).prefetch_related('device_type__manufacturer')
peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=rack.site)
if rack.group:
peer_racks = peer_racks.filter(group=rack.group)
else:
peer_racks = peer_racks.filter(group__isnull=True)
next_rack = peer_racks.filter(name__gt=rack.name).order_by('name').first()
prev_rack = peer_racks.filter(name__lt=rack.name).order_by('-name').first()
2020-06-01 11:43:49 -04:00
reservations = RackReservation.objects.restrict(request.user, 'view').filter(rack=rack)
power_feeds = PowerFeed.objects.restrict(request.user, 'view').filter(rack=rack).prefetch_related('power_panel')
return render(request, 'dcim/rack.html', {
'rack': rack,
'device_count': Device.objects.restrict(request.user, 'view').filter(rack=rack).count(),
'reservations': reservations,
2019-03-12 11:36:29 -04:00
'power_feeds': power_feeds,
'nonracked_devices': nonracked_devices,
'next_rack': next_rack,
'prev_rack': prev_rack,
})
2016-03-01 11:23:03 -05:00
class RackEditView(ObjectEditView):
queryset = Rack.objects.all()
model_form = forms.RackForm
template_name = 'dcim/rack_edit.html'
2016-03-01 11:23:03 -05:00
class RackDeleteView(ObjectDeleteView):
queryset = Rack.objects.all()
2016-03-01 11:23:03 -05:00
class RackBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Rack.objects.all()
model_form = forms.RackCSVForm
table = tables.RackTable
2016-03-01 11:23:03 -05:00
class RackBulkEditView(BulkEditView):
queryset = Rack.objects.prefetch_related('site', 'group', 'tenant', 'role')
filterset = filters.RackFilterSet
table = tables.RackTable
2016-05-18 16:02:53 -04:00
form = forms.RackBulkEditForm
2016-03-01 11:23:03 -05:00
class RackBulkDeleteView(BulkDeleteView):
queryset = Rack.objects.prefetch_related('site', 'group', 'tenant', 'role')
filterset = filters.RackFilterSet
table = tables.RackTable
2016-03-01 11:23:03 -05:00
#
# Rack reservations
#
class RackReservationListView(ObjectListView):
queryset = RackReservation.objects.prefetch_related('rack__site')
filterset = filters.RackReservationFilterSet
filterset_form = forms.RackReservationFilterForm
table = tables.RackReservationTable
2020-03-06 17:14:26 -05:00
action_buttons = ('export',)
class RackReservationView(ObjectView):
queryset = RackReservation.objects.prefetch_related('rack')
def get(self, request, pk):
rackreservation = get_object_or_404(self.queryset, pk=pk)
return render(request, 'dcim/rackreservation.html', {
'rackreservation': rackreservation,
})
class RackReservationEditView(ObjectEditView):
queryset = RackReservation.objects.all()
model_form = forms.RackReservationForm
template_name = 'dcim/rackreservation_edit.html'
def alter_obj(self, obj, request, args, kwargs):
if not obj.pk:
if 'rack' in request.GET:
obj.rack = get_object_or_404(Rack, pk=request.GET.get('rack'))
obj.user = request.user
return obj
class RackReservationDeleteView(ObjectDeleteView):
queryset = RackReservation.objects.all()
class RackReservationImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = RackReservation.objects.all()
2020-03-06 17:14:26 -05:00
model_form = forms.RackReservationCSVForm
table = tables.RackReservationTable
def _save_obj(self, obj_form, request):
"""
Assign the currently authenticated user to the RackReservation.
"""
instance = obj_form.save(commit=False)
instance.user = request.user
instance.save()
return instance
2020-03-06 17:14:26 -05:00
class RackReservationBulkEditView(BulkEditView):
queryset = RackReservation.objects.prefetch_related('rack', 'user')
filterset = filters.RackReservationFilterSet
table = tables.RackReservationTable
form = forms.RackReservationBulkEditForm
class RackReservationBulkDeleteView(BulkDeleteView):
queryset = RackReservation.objects.prefetch_related('rack', 'user')
filterset = filters.RackReservationFilterSet
table = tables.RackReservationTable
2016-05-13 15:22:31 -04:00
#
# Manufacturers
#
class ManufacturerListView(ObjectListView):
queryset = Manufacturer.objects.annotate(
devicetype_count=Count('device_types', distinct=True),
inventoryitem_count=Count('inventory_items', distinct=True),
platform_count=Count('platforms', distinct=True),
)
2016-05-18 16:02:53 -04:00
table = tables.ManufacturerTable
2016-05-13 15:22:31 -04:00
class ManufacturerEditView(ObjectEditView):
queryset = Manufacturer.objects.all()
model_form = forms.ManufacturerForm
2016-05-13 15:22:31 -04:00
class ManufacturerDeleteView(ObjectDeleteView):
queryset = Manufacturer.objects.all()
class ManufacturerBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Manufacturer.objects.all()
model_form = forms.ManufacturerCSVForm
table = tables.ManufacturerTable
class ManufacturerBulkDeleteView(BulkDeleteView):
queryset = Manufacturer.objects.annotate(devicetype_count=Count('device_types'))
table = tables.ManufacturerTable
2016-05-13 15:22:31 -04:00
#
# Device types
#
class DeviceTypeListView(ObjectListView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
filterset = filters.DeviceTypeFilterSet
filterset_form = forms.DeviceTypeFilterForm
table = tables.DeviceTypeTable
class DeviceTypeView(ObjectView):
queryset = DeviceType.objects.prefetch_related('manufacturer')
def get(self, request, pk):
devicetype = get_object_or_404(self.queryset, pk=pk)
instance_count = Device.objects.restrict(request.user).filter(device_type=devicetype).count()
# Component tables
consoleport_table = tables.ConsolePortTemplateTable(
2020-06-01 11:43:49 -04:00
ConsolePortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
orderable=False
)
consoleserverport_table = tables.ConsoleServerPortTemplateTable(
2020-06-01 11:43:49 -04:00
ConsoleServerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
orderable=False
)
powerport_table = tables.PowerPortTemplateTable(
2020-06-01 11:43:49 -04:00
PowerPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
orderable=False
)
poweroutlet_table = tables.PowerOutletTemplateTable(
2020-06-01 11:43:49 -04:00
PowerOutletTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
orderable=False
)
interface_table = tables.InterfaceTemplateTable(
2020-06-01 11:43:49 -04:00
list(InterfaceTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype)),
orderable=False
)
front_port_table = tables.FrontPortTemplateTable(
2020-06-01 11:43:49 -04:00
FrontPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
2018-10-03 14:04:16 -04:00
orderable=False
)
rear_port_table = tables.RearPortTemplateTable(
2020-06-01 11:43:49 -04:00
RearPortTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
2018-10-03 14:04:16 -04:00
orderable=False
)
devicebay_table = tables.DeviceBayTemplateTable(
2020-06-01 11:43:49 -04:00
DeviceBayTemplate.objects.restrict(request.user, 'view').filter(device_type=devicetype),
orderable=False
)
if request.user.has_perm('dcim.change_devicetype'):
consoleport_table.columns.show('pk')
consoleserverport_table.columns.show('pk')
powerport_table.columns.show('pk')
poweroutlet_table.columns.show('pk')
interface_table.columns.show('pk')
front_port_table.columns.show('pk')
rear_port_table.columns.show('pk')
devicebay_table.columns.show('pk')
return render(request, 'dcim/devicetype.html', {
'devicetype': devicetype,
'instance_count': instance_count,
'consoleport_table': consoleport_table,
'consoleserverport_table': consoleserverport_table,
'powerport_table': powerport_table,
'poweroutlet_table': poweroutlet_table,
'interface_table': interface_table,
'front_port_table': front_port_table,
'rear_port_table': rear_port_table,
'devicebay_table': devicebay_table,
})
class DeviceTypeEditView(ObjectEditView):
queryset = DeviceType.objects.all()
model_form = forms.DeviceTypeForm
template_name = 'dcim/devicetype_edit.html'
class DeviceTypeDeleteView(ObjectDeleteView):
queryset = DeviceType.objects.all()
class DeviceTypeImportView(ObjectImportView):
additional_permissions = [
2019-10-01 16:54:10 -04:00
'dcim.add_devicetype',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
'dcim.add_poweroutlettemplate',
'dcim.add_interfacetemplate',
'dcim.add_frontporttemplate',
'dcim.add_rearporttemplate',
'dcim.add_devicebaytemplate',
]
queryset = DeviceType.objects.all()
model_form = forms.DeviceTypeImportForm
related_object_forms = OrderedDict((
('console-ports', forms.ConsolePortTemplateImportForm),
('console-server-ports', forms.ConsoleServerPortTemplateImportForm),
('power-ports', forms.PowerPortTemplateImportForm),
('power-outlets', forms.PowerOutletTemplateImportForm),
('interfaces', forms.InterfaceTemplateImportForm),
('rear-ports', forms.RearPortTemplateImportForm),
('front-ports', forms.FrontPortTemplateImportForm),
('device-bays', forms.DeviceBayTemplateImportForm),
))
class DeviceTypeBulkEditView(BulkEditView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
filterset = filters.DeviceTypeFilterSet
table = tables.DeviceTypeTable
2016-05-18 16:02:53 -04:00
form = forms.DeviceTypeBulkEditForm
class DeviceTypeBulkDeleteView(BulkDeleteView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
filterset = filters.DeviceTypeFilterSet
table = tables.DeviceTypeTable
#
# Console port templates
#
class ConsolePortTemplateCreateView(ComponentCreateView):
queryset = ConsolePortTemplate.objects.all()
form = forms.ConsolePortTemplateCreateForm
model_form = forms.ConsolePortTemplateForm
template_name = 'dcim/device_component_add.html'
class ConsolePortTemplateEditView(ObjectEditView):
queryset = ConsolePortTemplate.objects.all()
model_form = forms.ConsolePortTemplateForm
class ConsolePortTemplateDeleteView(ObjectDeleteView):
queryset = ConsolePortTemplate.objects.all()
class ConsolePortTemplateBulkEditView(BulkEditView):
queryset = ConsolePortTemplate.objects.all()
table = tables.ConsolePortTemplateTable
form = forms.ConsolePortTemplateBulkEditForm
class ConsolePortTemplateBulkDeleteView(BulkDeleteView):
queryset = ConsolePortTemplate.objects.all()
table = tables.ConsolePortTemplateTable
#
# Console server port templates
#
class ConsoleServerPortTemplateCreateView(ComponentCreateView):
queryset = ConsoleServerPortTemplate.objects.all()
form = forms.ConsoleServerPortTemplateCreateForm
model_form = forms.ConsoleServerPortTemplateForm
template_name = 'dcim/device_component_add.html'
class ConsoleServerPortTemplateEditView(ObjectEditView):
queryset = ConsoleServerPortTemplate.objects.all()
model_form = forms.ConsoleServerPortTemplateForm
class ConsoleServerPortTemplateDeleteView(ObjectDeleteView):
queryset = ConsoleServerPortTemplate.objects.all()
class ConsoleServerPortTemplateBulkEditView(BulkEditView):
queryset = ConsoleServerPortTemplate.objects.all()
table = tables.ConsoleServerPortTemplateTable
form = forms.ConsoleServerPortTemplateBulkEditForm
class ConsoleServerPortTemplateBulkDeleteView(BulkDeleteView):
queryset = ConsoleServerPortTemplate.objects.all()
table = tables.ConsoleServerPortTemplateTable
#
# Power port templates
#
class PowerPortTemplateCreateView(ComponentCreateView):
queryset = PowerPortTemplate.objects.all()
form = forms.PowerPortTemplateCreateForm
model_form = forms.PowerPortTemplateForm
template_name = 'dcim/device_component_add.html'
class PowerPortTemplateEditView(ObjectEditView):
queryset = PowerPortTemplate.objects.all()
model_form = forms.PowerPortTemplateForm
class PowerPortTemplateDeleteView(ObjectDeleteView):
queryset = PowerPortTemplate.objects.all()
class PowerPortTemplateBulkEditView(BulkEditView):
queryset = PowerPortTemplate.objects.all()
table = tables.PowerPortTemplateTable
form = forms.PowerPortTemplateBulkEditForm
class PowerPortTemplateBulkDeleteView(BulkDeleteView):
queryset = PowerPortTemplate.objects.all()
table = tables.PowerPortTemplateTable
#
# Power outlet templates
#
class PowerOutletTemplateCreateView(ComponentCreateView):
queryset = PowerOutletTemplate.objects.all()
form = forms.PowerOutletTemplateCreateForm
model_form = forms.PowerOutletTemplateForm
template_name = 'dcim/device_component_add.html'
class PowerOutletTemplateEditView(ObjectEditView):
queryset = PowerOutletTemplate.objects.all()
model_form = forms.PowerOutletTemplateForm
class PowerOutletTemplateDeleteView(ObjectDeleteView):
queryset = PowerOutletTemplate.objects.all()
class PowerOutletTemplateBulkEditView(BulkEditView):
queryset = PowerOutletTemplate.objects.all()
table = tables.PowerOutletTemplateTable
form = forms.PowerOutletTemplateBulkEditForm
class PowerOutletTemplateBulkDeleteView(BulkDeleteView):
queryset = PowerOutletTemplate.objects.all()
table = tables.PowerOutletTemplateTable
#
# Interface templates
#
class InterfaceTemplateCreateView(ComponentCreateView):
queryset = InterfaceTemplate.objects.all()
form = forms.InterfaceTemplateCreateForm
model_form = forms.InterfaceTemplateForm
template_name = 'dcim/device_component_add.html'
class InterfaceTemplateEditView(ObjectEditView):
queryset = InterfaceTemplate.objects.all()
model_form = forms.InterfaceTemplateForm
class InterfaceTemplateDeleteView(ObjectDeleteView):
queryset = InterfaceTemplate.objects.all()
class InterfaceTemplateBulkEditView(BulkEditView):
queryset = InterfaceTemplate.objects.all()
table = tables.InterfaceTemplateTable
form = forms.InterfaceTemplateBulkEditForm
class InterfaceTemplateBulkDeleteView(BulkDeleteView):
queryset = InterfaceTemplate.objects.all()
table = tables.InterfaceTemplateTable
#
# Front port templates
#
class FrontPortTemplateCreateView(ComponentCreateView):
queryset = FrontPortTemplate.objects.all()
form = forms.FrontPortTemplateCreateForm
model_form = forms.FrontPortTemplateForm
2018-10-03 14:04:16 -04:00
template_name = 'dcim/device_component_add.html'
class FrontPortTemplateEditView(ObjectEditView):
queryset = FrontPortTemplate.objects.all()
model_form = forms.FrontPortTemplateForm
class FrontPortTemplateDeleteView(ObjectDeleteView):
queryset = FrontPortTemplate.objects.all()
class FrontPortTemplateBulkEditView(BulkEditView):
queryset = FrontPortTemplate.objects.all()
table = tables.FrontPortTemplateTable
form = forms.FrontPortTemplateBulkEditForm
class FrontPortTemplateBulkDeleteView(BulkDeleteView):
queryset = FrontPortTemplate.objects.all()
table = tables.FrontPortTemplateTable
2018-10-03 14:04:16 -04:00
#
# Rear port templates
#
class RearPortTemplateCreateView(ComponentCreateView):
queryset = RearPortTemplate.objects.all()
form = forms.RearPortTemplateCreateForm
model_form = forms.RearPortTemplateForm
2018-10-03 14:04:16 -04:00
template_name = 'dcim/device_component_add.html'
class RearPortTemplateEditView(ObjectEditView):
queryset = RearPortTemplate.objects.all()
model_form = forms.RearPortTemplateForm
class RearPortTemplateDeleteView(ObjectDeleteView):
queryset = RearPortTemplate.objects.all()
class RearPortTemplateBulkEditView(BulkEditView):
queryset = RearPortTemplate.objects.all()
table = tables.RearPortTemplateTable
form = forms.RearPortTemplateBulkEditForm
class RearPortTemplateBulkDeleteView(BulkDeleteView):
queryset = RearPortTemplate.objects.all()
table = tables.RearPortTemplateTable
2018-10-03 14:04:16 -04:00
#
# Device bay templates
#
class DeviceBayTemplateCreateView(ComponentCreateView):
queryset = DeviceBayTemplate.objects.all()
form = forms.DeviceBayTemplateCreateForm
model_form = forms.DeviceBayTemplateForm
template_name = 'dcim/device_component_add.html'
class DeviceBayTemplateEditView(ObjectEditView):
queryset = DeviceBayTemplate.objects.all()
model_form = forms.DeviceBayTemplateForm
class DeviceBayTemplateDeleteView(ObjectDeleteView):
queryset = DeviceBayTemplate.objects.all()
class DeviceBayTemplateBulkEditView(BulkEditView):
queryset = DeviceBayTemplate.objects.all()
table = tables.DeviceBayTemplateTable
form = forms.DeviceBayTemplateBulkEditForm
class DeviceBayTemplateBulkDeleteView(BulkDeleteView):
queryset = DeviceBayTemplate.objects.all()
table = tables.DeviceBayTemplateTable
2016-05-12 14:38:34 -04:00
#
# Device roles
#
class DeviceRoleListView(ObjectListView):
queryset = DeviceRole.objects.all()
2016-05-18 16:02:53 -04:00
table = tables.DeviceRoleTable
2016-05-12 14:38:34 -04:00
class DeviceRoleEditView(ObjectEditView):
queryset = DeviceRole.objects.all()
model_form = forms.DeviceRoleForm
2016-05-12 14:38:34 -04:00
class DeviceRoleDeleteView(ObjectDeleteView):
queryset = DeviceRole.objects.all()
class DeviceRoleBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = DeviceRole.objects.all()
model_form = forms.DeviceRoleCSVForm
table = tables.DeviceRoleTable
class DeviceRoleBulkDeleteView(BulkDeleteView):
queryset = DeviceRole.objects.all()
table = tables.DeviceRoleTable
2016-05-12 14:38:34 -04:00
2016-05-16 11:54:17 -04:00
#
# Platforms
#
class PlatformListView(ObjectListView):
queryset = Platform.objects.all()
2016-05-18 16:02:53 -04:00
table = tables.PlatformTable
2016-05-16 11:54:17 -04:00
class PlatformEditView(ObjectEditView):
queryset = Platform.objects.all()
model_form = forms.PlatformForm
2016-05-16 11:54:17 -04:00
class PlatformDeleteView(ObjectDeleteView):
queryset = Platform.objects.all()
class PlatformBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Platform.objects.all()
model_form = forms.PlatformCSVForm
table = tables.PlatformTable
class PlatformBulkDeleteView(BulkDeleteView):
queryset = Platform.objects.all()
table = tables.PlatformTable
2016-05-16 11:54:17 -04:00
2016-03-01 11:23:03 -05:00
#
# Devices
#
class DeviceListView(ObjectListView):
queryset = Device.objects.prefetch_related(
'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6'
)
filterset = filters.DeviceFilterSet
filterset_form = forms.DeviceFilterForm
2020-04-29 10:58:08 -04:00
table = tables.DeviceTable
template_name = 'dcim/device_list.html'
2016-03-01 11:23:03 -05:00
class DeviceView(ObjectView):
queryset = Device.objects.prefetch_related(
'site__region', 'rack__group', 'tenant__group', 'device_role', 'platform', 'primary_ip4', 'primary_ip6'
)
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk)
# VirtualChassis members
if device.virtual_chassis is not None:
2020-06-01 11:43:49 -04:00
vc_members = Device.objects.restrict(request.user, 'view').filter(
virtual_chassis=device.virtual_chassis
).order_by('vc_position')
else:
vc_members = []
# Console ports
2020-06-01 11:43:49 -04:00
console_ports = ConsolePort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'connected_endpoint__device', 'cable',
)
# Console server ports
2020-06-01 11:43:49 -04:00
consoleserverports = ConsoleServerPort.objects.restrict(request.user, 'view').filter(
device=device
).prefetch_related(
'connected_endpoint__device', 'cable',
)
# Power ports
2020-06-01 11:43:49 -04:00
power_ports = PowerPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'_connected_poweroutlet__device', 'cable',
)
# Power outlets
2020-06-01 11:43:49 -04:00
poweroutlets = PowerOutlet.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'connected_endpoint__device', 'cable', 'power_port',
)
# Interfaces
2020-06-01 11:43:49 -04:00
interfaces = device.vc_interfaces.restrict(request.user, 'view').filter(device=device).prefetch_related(
Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)),
Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)),
'lag', '_connected_interface__device', '_connected_circuittermination__circuit', 'cable',
'cable__termination_a', 'cable__termination_b', 'tags'
)
# Front ports
2020-06-01 11:43:49 -04:00
front_ports = FrontPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'rear_port', 'cable',
)
2018-10-03 14:04:16 -04:00
# Rear ports
2020-06-01 11:43:49 -04:00
rear_ports = RearPort.objects.restrict(request.user, 'view').filter(device=device).prefetch_related('cable')
2018-10-03 14:04:16 -04:00
# Device bays
2020-06-01 11:43:49 -04:00
device_bays = DeviceBay.objects.restrict(request.user, 'view').filter(device=device).prefetch_related(
'installed_device__device_type__manufacturer',
)
# Services
2020-06-01 11:43:49 -04:00
services = Service.objects.restrict(request.user, 'view').filter(device=device)
# Secrets
2020-06-01 11:43:49 -04:00
secrets = Secret.objects.restrict(request.user, 'view').filter(device=device)
# Find up to ten devices in the same site with the same functional role for quick reference.
2020-06-01 11:43:49 -04:00
related_devices = Device.objects.restrict(request.user, 'view').filter(
site=device.site, device_role=device.device_role
).exclude(
pk=device.pk
).prefetch_related(
'rack', 'device_type__manufacturer'
)[:10]
return render(request, 'dcim/device.html', {
'device': device,
'console_ports': console_ports,
'consoleserverports': consoleserverports,
'power_ports': power_ports,
'poweroutlets': poweroutlets,
'interfaces': interfaces,
'device_bays': device_bays,
'front_ports': front_ports,
'rear_ports': rear_ports,
'services': services,
'secrets': secrets,
'vc_members': vc_members,
'related_devices': related_devices,
'show_graphs': Graph.objects.filter(type__model='device').exists(),
'show_interface_graphs': Graph.objects.filter(type__model='interface').exists(),
})
class DeviceInventoryView(ObjectView):
queryset = Device.objects.all()
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk)
2020-06-01 11:43:49 -04:00
inventory_items = InventoryItem.objects.restrict(request.user, 'view').filter(
device=device, parent=None
).prefetch_related(
'manufacturer', 'child_items'
)
return render(request, 'dcim/device_inventory.html', {
'device': device,
'inventory_items': inventory_items,
'active_tab': 'inventory',
})
2016-03-01 11:23:03 -05:00
class DeviceStatusView(ObjectView):
additional_permissions = ['dcim.napalm_read_device']
queryset = Device.objects.all()
2017-07-14 16:07:28 -04:00
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk)
2017-07-14 16:07:28 -04:00
return render(request, 'dcim/device_status.html', {
'device': device,
'active_tab': 'status',
2017-07-14 16:07:28 -04:00
})
class DeviceLLDPNeighborsView(ObjectView):
additional_permissions = ['dcim.napalm_read_device']
queryset = Device.objects.all()
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk)
2020-06-01 11:43:49 -04:00
interfaces = device.vc_interfaces.restrict(request.user, 'view').exclude(
type__in=NONCONNECTABLE_IFACE_TYPES
).prefetch_related(
'_connected_interface__device'
)
return render(request, 'dcim/device_lldp_neighbors.html', {
'device': device,
'interfaces': interfaces,
'active_tab': 'lldp-neighbors',
})
2016-03-01 11:23:03 -05:00
class DeviceConfigView(ObjectView):
additional_permissions = ['dcim.napalm_read_device']
queryset = Device.objects.all()
2017-07-17 13:19:25 -04:00
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk)
2017-07-17 13:19:25 -04:00
return render(request, 'dcim/device_config.html', {
'device': device,
'active_tab': 'config',
2017-07-17 13:19:25 -04:00
})
class DeviceConfigContextView(ObjectConfigContextView):
queryset = Device.objects.all()
base_template = 'dcim/device.html'
2018-06-27 16:02:34 -04:00
class DeviceEditView(ObjectEditView):
queryset = Device.objects.all()
model_form = forms.DeviceForm
template_name = 'dcim/device_edit.html'
2016-03-01 11:23:03 -05:00
class DeviceDeleteView(ObjectDeleteView):
queryset = Device.objects.all()
2016-03-01 11:23:03 -05:00
class DeviceBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Device.objects.all()
model_form = forms.DeviceCSVForm
2016-05-18 16:02:53 -04:00
table = tables.DeviceImportTable
2016-03-01 11:23:03 -05:00
template_name = 'dcim/device_import.html'
class ChildDeviceBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Device.objects.all()
model_form = forms.ChildDeviceCSVForm
table = tables.DeviceImportTable
template_name = 'dcim/device_import_child.html'
def _save_obj(self, obj_form, request):
obj = obj_form.save()
# Save the reverse relation to the parent device bay
device_bay = obj.parent_bay
device_bay.installed_device = obj
device_bay.save()
return obj
class DeviceBulkEditView(BulkEditView):
queryset = Device.objects.prefetch_related('tenant', 'site', 'rack', 'device_role', 'device_type__manufacturer')
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
2016-05-18 16:02:53 -04:00
form = forms.DeviceBulkEditForm
2016-03-01 11:23:03 -05:00
class DeviceBulkDeleteView(BulkDeleteView):
queryset = Device.objects.prefetch_related('tenant', 'site', 'rack', 'device_role', 'device_type__manufacturer')
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
2016-03-01 11:23:03 -05:00
2016-12-21 15:26:56 -05:00
#
# Console ports
#
class ConsolePortListView(ObjectListView):
queryset = ConsolePort.objects.prefetch_related('device', 'cable')
filterset = filters.ConsolePortFilterSet
filterset_form = forms.ConsolePortFilterForm
table = tables.ConsolePortTable
action_buttons = ('import', 'export')
class ConsolePortView(ObjectView):
queryset = ConsolePort.objects.all()
class ConsolePortCreateView(ComponentCreateView):
queryset = ConsolePort.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.ConsolePortCreateForm
model_form = forms.ConsolePortForm
template_name = 'dcim/device_component_add.html'
2016-03-01 11:23:03 -05:00
class ConsolePortEditView(ObjectEditView):
queryset = ConsolePort.objects.all()
model_form = forms.ConsolePortForm
2016-03-01 11:23:03 -05:00
class ConsolePortDeleteView(ObjectDeleteView):
queryset = ConsolePort.objects.all()
2016-03-01 11:23:03 -05:00
class ConsolePortBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = ConsolePort.objects.all()
model_form = forms.ConsolePortCSVForm
table = tables.ConsolePortTable
class ConsolePortBulkEditView(BulkEditView):
queryset = ConsolePort.objects.all()
filterset = filters.ConsolePortFilterSet
table = tables.ConsolePortTable
form = forms.ConsolePortBulkEditForm
class ConsolePortBulkRenameView(BulkRenameView):
queryset = ConsolePort.objects.all()
class ConsolePortBulkDisconnectView(BulkDisconnectView):
queryset = ConsolePort.objects.all()
class ConsolePortBulkDeleteView(BulkDeleteView):
queryset = ConsolePort.objects.all()
filterset = filters.ConsolePortFilterSet
table = tables.ConsolePortTable
2016-03-01 11:23:03 -05:00
#
# Console server ports
#
class ConsoleServerPortListView(ObjectListView):
queryset = ConsoleServerPort.objects.prefetch_related('device', 'cable')
filterset = filters.ConsoleServerPortFilterSet
filterset_form = forms.ConsoleServerPortFilterForm
table = tables.ConsoleServerPortTable
action_buttons = ('import', 'export')
class ConsoleServerPortView(ObjectView):
queryset = ConsoleServerPort.objects.all()
class ConsoleServerPortCreateView(ComponentCreateView):
queryset = ConsoleServerPort.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.ConsoleServerPortCreateForm
model_form = forms.ConsoleServerPortForm
template_name = 'dcim/device_component_add.html'
2016-03-01 11:23:03 -05:00
class ConsoleServerPortEditView(ObjectEditView):
queryset = ConsoleServerPort.objects.all()
model_form = forms.ConsoleServerPortForm
2016-03-01 11:23:03 -05:00
class ConsoleServerPortDeleteView(ObjectDeleteView):
queryset = ConsoleServerPort.objects.all()
2016-03-01 11:23:03 -05:00
class ConsoleServerPortBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = ConsoleServerPort.objects.all()
model_form = forms.ConsoleServerPortCSVForm
table = tables.ConsoleServerPortTable
class ConsoleServerPortBulkEditView(BulkEditView):
queryset = ConsoleServerPort.objects.all()
filterset = filters.ConsoleServerPortFilterSet
table = tables.ConsoleServerPortTable
form = forms.ConsoleServerPortBulkEditForm
class ConsoleServerPortBulkRenameView(BulkRenameView):
queryset = ConsoleServerPort.objects.all()
class ConsoleServerPortBulkDisconnectView(BulkDisconnectView):
queryset = ConsoleServerPort.objects.all()
class ConsoleServerPortBulkDeleteView(BulkDeleteView):
queryset = ConsoleServerPort.objects.all()
filterset = filters.ConsoleServerPortFilterSet
table = tables.ConsoleServerPortTable
2016-03-01 11:23:03 -05:00
#
# Power ports
#
class PowerPortListView(ObjectListView):
queryset = PowerPort.objects.prefetch_related('device', 'cable')
filterset = filters.PowerPortFilterSet
filterset_form = forms.PowerPortFilterForm
table = tables.PowerPortTable
action_buttons = ('import', 'export')
class PowerPortView(ObjectView):
queryset = PowerPort.objects.all()
class PowerPortCreateView(ComponentCreateView):
queryset = PowerPort.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.PowerPortCreateForm
model_form = forms.PowerPortForm
template_name = 'dcim/device_component_add.html'
2016-03-01 11:23:03 -05:00
class PowerPortEditView(ObjectEditView):
queryset = PowerPort.objects.all()
model_form = forms.PowerPortForm
2016-03-01 11:23:03 -05:00
class PowerPortDeleteView(ObjectDeleteView):
queryset = PowerPort.objects.all()
2016-03-01 11:23:03 -05:00
class PowerPortBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = PowerPort.objects.all()
model_form = forms.PowerPortCSVForm
table = tables.PowerPortTable
class PowerPortBulkEditView(BulkEditView):
queryset = PowerPort.objects.all()
filterset = filters.PowerPortFilterSet
table = tables.PowerPortTable
form = forms.PowerPortBulkEditForm
class PowerPortBulkRenameView(BulkRenameView):
queryset = PowerPort.objects.all()
class PowerPortBulkDisconnectView(BulkDisconnectView):
queryset = PowerPort.objects.all()
class PowerPortBulkDeleteView(BulkDeleteView):
queryset = PowerPort.objects.all()
filterset = filters.PowerPortFilterSet
table = tables.PowerPortTable
2016-03-01 11:23:03 -05:00
#
# Power outlets
#
class PowerOutletListView(ObjectListView):
queryset = PowerOutlet.objects.prefetch_related('device', 'cable')
filterset = filters.PowerOutletFilterSet
filterset_form = forms.PowerOutletFilterForm
table = tables.PowerOutletTable
action_buttons = ('import', 'export')
class PowerOutletView(ObjectView):
queryset = PowerOutlet.objects.all()
class PowerOutletCreateView(ComponentCreateView):
queryset = PowerOutlet.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.PowerOutletCreateForm
model_form = forms.PowerOutletForm
template_name = 'dcim/device_component_add.html'
2016-03-01 11:23:03 -05:00
class PowerOutletEditView(ObjectEditView):
queryset = PowerOutlet.objects.all()
model_form = forms.PowerOutletForm
2016-03-01 11:23:03 -05:00
class PowerOutletDeleteView(ObjectDeleteView):
queryset = PowerOutlet.objects.all()
2016-03-01 11:23:03 -05:00
class PowerOutletBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = PowerOutlet.objects.all()
model_form = forms.PowerOutletCSVForm
table = tables.PowerOutletTable
class PowerOutletBulkEditView(BulkEditView):
queryset = PowerOutlet.objects.all()
filterset = filters.PowerOutletFilterSet
table = tables.PowerOutletTable
form = forms.PowerOutletBulkEditForm
class PowerOutletBulkRenameView(BulkRenameView):
queryset = PowerOutlet.objects.all()
class PowerOutletBulkDisconnectView(BulkDisconnectView):
queryset = PowerOutlet.objects.all()
class PowerOutletBulkDeleteView(BulkDeleteView):
queryset = PowerOutlet.objects.all()
filterset = filters.PowerOutletFilterSet
table = tables.PowerOutletTable
2016-03-01 11:23:03 -05:00
#
# Interfaces
#
class InterfaceListView(ObjectListView):
queryset = Interface.objects.prefetch_related('device', 'cable')
filterset = filters.InterfaceFilterSet
filterset_form = forms.InterfaceFilterForm
table = tables.InterfaceTable
action_buttons = ('import', 'export')
class InterfaceView(ObjectView):
queryset = Interface.objects.all()
2018-07-11 15:30:54 -04:00
def get(self, request, pk):
interface = get_object_or_404(self.queryset, pk=pk)
2018-07-11 15:30:54 -04:00
# Get assigned IP addresses
ipaddress_table = InterfaceIPAddressTable(
data=interface.ip_addresses.restrict(request.user, 'view').prefetch_related('vrf', 'tenant'),
2018-07-11 15:30:54 -04:00
orderable=False
)
# Get assigned VLANs and annotate whether each is tagged or untagged
vlans = []
if interface.untagged_vlan is not None:
vlans.append(interface.untagged_vlan)
vlans[0].tagged = False
for vlan in interface.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'):
2018-07-11 15:30:54 -04:00
vlan.tagged = True
vlans.append(vlan)
vlan_table = InterfaceVLANTable(
interface=interface,
data=vlans,
orderable=False
)
return render(request, 'dcim/interface.html', {
'instance': interface,
'connected_interface': interface._connected_interface,
'connected_circuittermination': interface._connected_circuittermination,
2018-07-11 15:30:54 -04:00
'ipaddress_table': ipaddress_table,
'vlan_table': vlan_table,
})
class InterfaceCreateView(ComponentCreateView):
queryset = Interface.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.InterfaceCreateForm
model_form = forms.InterfaceForm
template_name = 'dcim/device_component_add.html'
2016-03-01 11:23:03 -05:00
class InterfaceEditView(ObjectEditView):
queryset = Interface.objects.all()
model_form = forms.InterfaceForm
template_name = 'dcim/interface_edit.html'
2016-03-01 11:23:03 -05:00
class InterfaceDeleteView(ObjectDeleteView):
queryset = Interface.objects.all()
2016-03-01 11:23:03 -05:00
class InterfaceBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Interface.objects.all()
model_form = forms.InterfaceCSVForm
table = tables.InterfaceTable
class InterfaceBulkEditView(BulkEditView):
queryset = Interface.objects.all()
filterset = filters.InterfaceFilterSet
table = tables.InterfaceTable
2016-10-14 16:38:46 -04:00
form = forms.InterfaceBulkEditForm
class InterfaceBulkRenameView(BulkRenameView):
queryset = Interface.objects.all()
class InterfaceBulkDisconnectView(BulkDisconnectView):
queryset = Interface.objects.all()
class InterfaceBulkDeleteView(BulkDeleteView):
queryset = Interface.objects.all()
filterset = filters.InterfaceFilterSet
table = tables.InterfaceTable
2018-10-03 14:04:16 -04:00
#
# Front ports
2018-10-03 14:04:16 -04:00
#
class FrontPortListView(ObjectListView):
queryset = FrontPort.objects.prefetch_related('device', 'cable')
filterset = filters.FrontPortFilterSet
filterset_form = forms.FrontPortFilterForm
table = tables.FrontPortTable
action_buttons = ('import', 'export')
class FrontPortView(ObjectView):
queryset = FrontPort.objects.all()
class FrontPortCreateView(ComponentCreateView):
queryset = FrontPort.objects.all()
form = forms.FrontPortCreateForm
model_form = forms.FrontPortForm
2018-10-03 14:04:16 -04:00
template_name = 'dcim/device_component_add.html'
class FrontPortEditView(ObjectEditView):
queryset = FrontPort.objects.all()
model_form = forms.FrontPortForm
2018-10-03 14:04:16 -04:00
class FrontPortDeleteView(ObjectDeleteView):
queryset = FrontPort.objects.all()
2018-10-03 14:04:16 -04:00
class FrontPortBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = FrontPort.objects.all()
model_form = forms.FrontPortCSVForm
table = tables.FrontPortTable
class FrontPortBulkEditView(BulkEditView):
queryset = FrontPort.objects.all()
filterset = filters.FrontPortFilterSet
table = tables.FrontPortTable
form = forms.FrontPortBulkEditForm
class FrontPortBulkRenameView(BulkRenameView):
queryset = FrontPort.objects.all()
2018-10-03 14:04:16 -04:00
class FrontPortBulkDisconnectView(BulkDisconnectView):
queryset = FrontPort.objects.all()
class FrontPortBulkDeleteView(BulkDeleteView):
queryset = FrontPort.objects.all()
filterset = filters.FrontPortFilterSet
table = tables.FrontPortTable
2018-10-03 14:04:16 -04:00
#
# Rear ports
2018-10-03 14:04:16 -04:00
#
class RearPortListView(ObjectListView):
queryset = RearPort.objects.prefetch_related('device', 'cable')
filterset = filters.RearPortFilterSet
filterset_form = forms.RearPortFilterForm
table = tables.RearPortTable
action_buttons = ('import', 'export')
class RearPortView(ObjectView):
queryset = RearPort.objects.all()
class RearPortCreateView(ComponentCreateView):
queryset = RearPort.objects.all()
form = forms.RearPortCreateForm
model_form = forms.RearPortForm
2018-10-03 14:04:16 -04:00
template_name = 'dcim/device_component_add.html'
class RearPortEditView(ObjectEditView):
queryset = RearPort.objects.all()
model_form = forms.RearPortForm
2018-10-03 14:04:16 -04:00
class RearPortDeleteView(ObjectDeleteView):
queryset = RearPort.objects.all()
2018-10-03 14:04:16 -04:00
class RearPortBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = RearPort.objects.all()
model_form = forms.RearPortCSVForm
table = tables.RearPortTable
class RearPortBulkEditView(BulkEditView):
queryset = RearPort.objects.all()
filterset = filters.RearPortFilterSet
table = tables.RearPortTable
form = forms.RearPortBulkEditForm
class RearPortBulkRenameView(BulkRenameView):
queryset = RearPort.objects.all()
2018-10-03 14:04:16 -04:00
class RearPortBulkDisconnectView(BulkDisconnectView):
queryset = RearPort.objects.all()
class RearPortBulkDeleteView(BulkDeleteView):
queryset = RearPort.objects.all()
filterset = filters.RearPortFilterSet
table = tables.RearPortTable
2018-10-03 14:04:16 -04:00
#
# Device bays
#
class DeviceBayListView(ObjectListView):
queryset = DeviceBay.objects.prefetch_related('device', 'installed_device')
filterset = filters.DeviceBayFilterSet
filterset_form = forms.DeviceBayFilterForm
table = tables.DeviceBayTable
action_buttons = ('import', 'export')
class DeviceBayView(ObjectView):
queryset = DeviceBay.objects.all()
class DeviceBayCreateView(ComponentCreateView):
queryset = DeviceBay.objects.all()
2016-12-21 15:26:56 -05:00
form = forms.DeviceBayCreateForm
model_form = forms.DeviceBayForm
template_name = 'dcim/device_component_add.html'
class DeviceBayEditView(ObjectEditView):
queryset = DeviceBay.objects.all()
model_form = forms.DeviceBayForm
class DeviceBayDeleteView(ObjectDeleteView):
queryset = DeviceBay.objects.all()
class DeviceBayPopulateView(ObjectEditView):
queryset = DeviceBay.objects.all()
def get(self, request, pk):
device_bay = get_object_or_404(self.queryset, pk=pk)
form = forms.PopulateDeviceBayForm(device_bay)
return render(request, 'dcim/devicebay_populate.html', {
'device_bay': device_bay,
'form': form,
'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}),
})
def post(self, request, pk):
device_bay = get_object_or_404(self.queryset, pk=pk)
form = forms.PopulateDeviceBayForm(device_bay, request.POST)
if form.is_valid():
device_bay.installed_device = form.cleaned_data['installed_device']
device_bay.save()
messages.success(request, "Added {} to {}.".format(device_bay.installed_device, device_bay))
return redirect('dcim:device', pk=device_bay.device.pk)
return render(request, 'dcim/devicebay_populate.html', {
'device_bay': device_bay,
'form': form,
'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}),
})
class DeviceBayDepopulateView(ObjectEditView):
queryset = DeviceBay.objects.all()
def get(self, request, pk):
device_bay = get_object_or_404(self.queryset, pk=pk)
form = ConfirmationForm()
return render(request, 'dcim/devicebay_depopulate.html', {
'device_bay': device_bay,
'form': form,
'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}),
})
def post(self, request, pk):
device_bay = get_object_or_404(self.queryset, pk=pk)
form = ConfirmationForm(request.POST)
if form.is_valid():
removed_device = device_bay.installed_device
device_bay.installed_device = None
device_bay.save()
2017-05-24 11:33:11 -04:00
messages.success(request, "{} has been removed from {}.".format(removed_device, device_bay))
return redirect('dcim:device', pk=device_bay.device.pk)
return render(request, 'dcim/devicebay_depopulate.html', {
'device_bay': device_bay,
'form': form,
'return_url': reverse('dcim:device', kwargs={'pk': device_bay.device.pk}),
})
class DeviceBayBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = DeviceBay.objects.all()
model_form = forms.DeviceBayCSVForm
table = tables.DeviceBayTable
class DeviceBayBulkEditView(BulkEditView):
queryset = DeviceBay.objects.all()
filterset = filters.DeviceBayFilterSet
table = tables.DeviceBayTable
form = forms.DeviceBayBulkEditForm
class DeviceBayBulkRenameView(BulkRenameView):
queryset = DeviceBay.objects.all()
class DeviceBayBulkDeleteView(BulkDeleteView):
queryset = DeviceBay.objects.all()
filterset = filters.DeviceBayFilterSet
table = tables.DeviceBayTable
#
# Inventory items
#
class InventoryItemListView(ObjectListView):
queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer')
filterset = filters.InventoryItemFilterSet
filterset_form = forms.InventoryItemFilterForm
table = tables.InventoryItemTable
action_buttons = ('import', 'export')
class InventoryItemView(ObjectView):
queryset = InventoryItem.objects.all()
class InventoryItemEditView(ObjectEditView):
queryset = InventoryItem.objects.all()
model_form = forms.InventoryItemForm
class InventoryItemCreateView(ComponentCreateView):
queryset = InventoryItem.objects.all()
form = forms.InventoryItemCreateForm
model_form = forms.InventoryItemForm
template_name = 'dcim/device_component_add.html'
class InventoryItemDeleteView(ObjectDeleteView):
queryset = InventoryItem.objects.all()
class InventoryItemBulkImportView(BulkImportView):
queryset = InventoryItem.objects.all()
model_form = forms.InventoryItemCSVForm
table = tables.InventoryItemTable
class InventoryItemBulkEditView(BulkEditView):
queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer')
filterset = filters.InventoryItemFilterSet
table = tables.InventoryItemTable
form = forms.InventoryItemBulkEditForm
class InventoryItemBulkDeleteView(BulkDeleteView):
queryset = InventoryItem.objects.prefetch_related('device', 'manufacturer')
table = tables.InventoryItemTable
template_name = 'dcim/inventoryitem_bulk_delete.html'
2016-12-21 15:26:56 -05:00
#
# Bulk Device component creation
2016-12-21 15:26:56 -05:00
#
class DeviceBulkAddConsolePortView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.ConsolePortBulkCreateForm
queryset = ConsolePort.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.ConsolePortForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
class DeviceBulkAddConsoleServerPortView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.ConsoleServerPortBulkCreateForm
queryset = ConsoleServerPort.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.ConsoleServerPortForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
class DeviceBulkAddPowerPortView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.PowerPortBulkCreateForm
queryset = PowerPort.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.PowerPortForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
class DeviceBulkAddPowerOutletView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.PowerOutletBulkCreateForm
queryset = PowerOutlet.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.PowerOutletForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
class DeviceBulkAddInterfaceView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.InterfaceBulkCreateForm
queryset = Interface.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.InterfaceForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
# class DeviceBulkAddFrontPortView(BulkComponentCreateView):
2020-04-22 11:26:04 -04:00
# parent_model = Device
# parent_field = 'device'
# form = forms.FrontPortBulkCreateForm
# queryset = FrontPort.objects.all()
2020-04-22 11:26:04 -04:00
# model_form = forms.FrontPortForm
# filterset = filters.DeviceFilterSet
# table = tables.DeviceTable
# default_return_url = 'dcim:device_list'
class DeviceBulkAddRearPortView(BulkComponentCreateView):
2020-04-22 11:26:04 -04:00
parent_model = Device
parent_field = 'device'
form = forms.RearPortBulkCreateForm
queryset = RearPort.objects.all()
2020-04-22 11:26:04 -04:00
model_form = forms.RearPortForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
class DeviceBulkAddDeviceBayView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.DeviceBayBulkCreateForm
queryset = DeviceBay.objects.all()
2016-12-21 15:26:56 -05:00
model_form = forms.DeviceBayForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2016-12-21 15:26:56 -05:00
class DeviceBulkAddInventoryItemView(BulkComponentCreateView):
parent_model = Device
parent_field = 'device'
form = forms.InventoryItemBulkCreateForm
queryset = InventoryItem.objects.all()
model_form = forms.InventoryItemForm
filterset = filters.DeviceFilterSet
table = tables.DeviceTable
default_return_url = 'dcim:device_list'
2018-10-24 14:24:02 -04:00
#
# Cables
#
class CableListView(ObjectListView):
2018-10-24 14:24:02 -04:00
queryset = Cable.objects.prefetch_related(
'termination_a', 'termination_b'
2018-10-24 14:24:02 -04:00
)
filterset = filters.CableFilterSet
filterset_form = forms.CableFilterForm
2018-10-24 14:24:02 -04:00
table = tables.CableTable
action_buttons = ('import', 'export')
2018-10-24 14:24:02 -04:00
class CableView(ObjectView):
queryset = Cable.objects.all()
2018-10-25 15:51:12 -04:00
def get(self, request, pk):
cable = get_object_or_404(self.queryset, pk=pk)
2018-10-25 15:51:12 -04:00
return render(request, 'dcim/cable.html', {
'cable': cable,
})
class CableTraceView(ObjectView):
2018-10-31 17:05:25 -04:00
"""
Trace a cable path beginning from the given termination.
"""
additional_permissions = ['dcim.view_cable']
2018-10-31 17:05:25 -04:00
def dispatch(self, request, *args, **kwargs):
model = kwargs.pop('model')
self.queryset = model.objects.all()
2018-10-31 17:05:25 -04:00
return super().dispatch(request, *args, **kwargs)
def get(self, request, pk):
obj = get_object_or_404(self.queryset, pk=pk)
path, split_ends = obj.trace()
total_length = sum(
[entry[1]._abs_length for entry in path if entry[1] and entry[1]._abs_length]
)
2018-10-31 17:05:25 -04:00
return render(request, 'dcim/cable_trace.html', {
'obj': obj,
'trace': path,
'split_ends': split_ends,
2020-01-08 10:49:58 +00:00
'total_length': total_length,
2018-10-31 17:05:25 -04:00
})
class CableCreateView(ObjectEditView):
queryset = Cable.objects.all()
2018-10-24 14:24:02 -04:00
template_name = 'dcim/cable_connect.html'
2019-03-21 17:47:43 -04:00
def dispatch(self, request, *args, **kwargs):
2018-10-24 14:24:02 -04:00
# Set the model_form class based on the type of component being connected
self.model_form = {
'console-port': forms.ConnectCableToConsolePortForm,
'console-server-port': forms.ConnectCableToConsoleServerPortForm,
'power-port': forms.ConnectCableToPowerPortForm,
'power-outlet': forms.ConnectCableToPowerOutletForm,
'interface': forms.ConnectCableToInterfaceForm,
'front-port': forms.ConnectCableToFrontPortForm,
'rear-port': forms.ConnectCableToRearPortForm,
'power-feed': forms.ConnectCableToPowerFeedForm,
'circuit-termination': forms.ConnectCableToCircuitTerminationForm,
}[kwargs.get('termination_b_type')]
2019-03-21 17:47:43 -04:00
return super().dispatch(request, *args, **kwargs)
def alter_obj(self, obj, request, url_args, url_kwargs):
termination_a_type = url_kwargs.get('termination_a_type')
termination_a_id = url_kwargs.get('termination_a_id')
termination_b_type_name = url_kwargs.get('termination_b_type')
self.termination_b_type = ContentType.objects.get(model=termination_b_type_name.replace('-', ''))
# Initialize Cable termination attributes
obj.termination_a = termination_a_type.objects.get(pk=termination_a_id)
obj.termination_b_type = self.termination_b_type
return obj
2019-03-21 17:47:43 -04:00
def get(self, request, *args, **kwargs):
obj = self.alter_obj(self.get_object(kwargs), request, args, kwargs)
2019-03-21 17:47:43 -04:00
# Parse initial data manually to avoid setting field values as lists
initial_data = {k: request.GET[k] for k in request.GET}
# Set initial site and rack based on side A termination (if not already set)
if 'termination_b_site' not in initial_data:
initial_data['termination_b_site'] = getattr(obj.termination_a.parent, 'site', None)
if 'termination_b_rack' not in initial_data:
initial_data['termination_b_rack'] = getattr(obj.termination_a.parent, 'rack', None)
2019-03-21 17:47:43 -04:00
form = self.model_form(instance=obj, initial=initial_data)
2019-03-21 17:47:43 -04:00
return render(request, self.template_name, {
'obj': obj,
2019-03-21 17:47:43 -04:00
'obj_type': Cable._meta.verbose_name,
'termination_b_type': self.termination_b_type.name,
2019-03-21 17:47:43 -04:00
'form': form,
'return_url': self.get_return_url(request, obj),
2019-03-21 17:47:43 -04:00
})
2018-10-24 14:24:02 -04:00
class CableEditView(ObjectEditView):
queryset = Cable.objects.all()
2018-10-25 15:51:12 -04:00
model_form = forms.CableForm
template_name = 'dcim/cable_edit.html'
2018-10-25 15:51:12 -04:00
class CableDeleteView(ObjectDeleteView):
queryset = Cable.objects.all()
2018-10-24 14:24:02 -04:00
class CableBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = Cable.objects.all()
2018-10-31 17:05:25 -04:00
model_form = forms.CableCSVForm
table = tables.CableTable
class CableBulkEditView(BulkEditView):
queryset = Cable.objects.prefetch_related('termination_a', 'termination_b')
filterset = filters.CableFilterSet
table = tables.CableTable
form = forms.CableBulkEditForm
class CableBulkDeleteView(BulkDeleteView):
queryset = Cable.objects.prefetch_related('termination_a', 'termination_b')
filterset = filters.CableFilterSet
table = tables.CableTable
2016-03-01 11:23:03 -05:00
#
# Connections
#
class ConsoleConnectionsListView(ObjectListView):
queryset = ConsolePort.objects.prefetch_related(
'device', 'connected_endpoint__device'
).filter(
connected_endpoint__isnull=False
).order_by(
'cable', 'connected_endpoint__device__name', 'connected_endpoint__name'
)
filterset = filters.ConsoleConnectionFilterSet
filterset_form = forms.ConsoleConnectionFilterForm
2016-05-18 16:02:53 -04:00
table = tables.ConsoleConnectionTable
2016-03-01 11:23:03 -05:00
template_name = 'dcim/console_connections_list.html'
def queryset_to_csv(self):
csv_data = [
# Headers
','.join(['console_server', 'port', 'device', 'console_port', 'connection_status'])
]
for obj in self.queryset:
csv = csv_format([
obj.connected_endpoint.device.identifier if obj.connected_endpoint else None,
obj.connected_endpoint.name if obj.connected_endpoint else None,
obj.device.identifier,
obj.name,
obj.get_connection_status_display(),
])
csv_data.append(csv)
return '\n'.join(csv_data)
2016-03-01 11:23:03 -05:00
class PowerConnectionsListView(ObjectListView):
queryset = PowerPort.objects.prefetch_related(
2019-03-21 17:47:43 -04:00
'device', '_connected_poweroutlet__device'
).filter(
2019-03-21 17:47:43 -04:00
_connected_poweroutlet__isnull=False
).order_by(
2019-03-21 17:47:43 -04:00
'cable', '_connected_poweroutlet__device__name', '_connected_poweroutlet__name'
)
filterset = filters.PowerConnectionFilterSet
filterset_form = forms.PowerConnectionFilterForm
2016-05-18 16:02:53 -04:00
table = tables.PowerConnectionTable
2016-03-01 11:23:03 -05:00
template_name = 'dcim/power_connections_list.html'
def queryset_to_csv(self):
csv_data = [
# Headers
','.join(['pdu', 'outlet', 'device', 'power_port', 'connection_status'])
]
for obj in self.queryset:
csv = csv_format([
obj.connected_endpoint.device.identifier if obj.connected_endpoint else None,
obj.connected_endpoint.name if obj.connected_endpoint else None,
obj.device.identifier,
obj.name,
obj.get_connection_status_display(),
])
csv_data.append(csv)
return '\n'.join(csv_data)
2016-03-01 11:23:03 -05:00
class InterfaceConnectionsListView(ObjectListView):
queryset = Interface.objects.prefetch_related(
'device', 'cable', '_connected_interface__device'
).filter(
# Avoid duplicate connections by only selecting the lower PK in a connected pair
_connected_interface__isnull=False,
pk__lt=F('_connected_interface')
).order_by(
'device'
)
filterset = filters.InterfaceConnectionFilterSet
filterset_form = forms.InterfaceConnectionFilterForm
2016-05-18 16:02:53 -04:00
table = tables.InterfaceConnectionTable
2016-03-01 11:23:03 -05:00
template_name = 'dcim/interface_connections_list.html'
def queryset_to_csv(self):
csv_data = [
# Headers
','.join([
'device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status'
])
]
for obj in self.queryset:
csv = csv_format([
obj.connected_endpoint.device.identifier if obj.connected_endpoint else None,
obj.connected_endpoint.name if obj.connected_endpoint else None,
obj.device.identifier,
obj.name,
obj.get_connection_status_display(),
])
csv_data.append(csv)
return '\n'.join(csv_data)
2016-03-01 11:23:03 -05:00
#
# Virtual chassis
#
class VirtualChassisListView(ObjectListView):
queryset = VirtualChassis.objects.prefetch_related('master').annotate(member_count=Count('members'))
table = tables.VirtualChassisTable
filterset = filters.VirtualChassisFilterSet
filterset_form = forms.VirtualChassisFilterForm
action_buttons = ('export',)
class VirtualChassisView(ObjectView):
queryset = VirtualChassis.objects.all()
def get(self, request, pk):
virtualchassis = get_object_or_404(self.queryset, pk=pk)
members = Device.objects.restrict(request.user).filter(virtual_chassis=virtualchassis)
return render(request, 'dcim/virtualchassis.html', {
'virtualchassis': virtualchassis,
'members': members,
})
class VirtualChassisCreateView(ObjectEditView):
queryset = VirtualChassis.objects.all()
model_form = forms.VirtualChassisCreateForm
template_name = 'dcim/virtualchassis_add.html'
class VirtualChassisEditView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
queryset = VirtualChassis.objects.all()
def get_required_permission(self):
return 'dcim.change_virtualchassis'
def get(self, request, pk):
virtual_chassis = get_object_or_404(self.queryset, pk=pk)
2018-02-14 12:05:00 -05:00
VCMemberFormSet = modelformset_factory(
model=Device,
form=forms.DeviceVCMembershipForm,
formset=forms.BaseVCMemberFormSet,
extra=0
)
members_queryset = virtual_chassis.members.prefetch_related('rack').order_by('vc_position')
vc_form = forms.VirtualChassisForm(instance=virtual_chassis)
2018-02-14 12:05:00 -05:00
vc_form.fields['master'].queryset = members_queryset
formset = VCMemberFormSet(queryset=members_queryset)
return render(request, 'dcim/virtualchassis_edit.html', {
'vc_form': vc_form,
'formset': formset,
'return_url': self.get_return_url(request, virtual_chassis),
})
def post(self, request, pk):
virtual_chassis = get_object_or_404(self.queryset, pk=pk)
2018-02-14 12:05:00 -05:00
VCMemberFormSet = modelformset_factory(
model=Device,
form=forms.DeviceVCMembershipForm,
formset=forms.BaseVCMemberFormSet,
extra=0
)
members_queryset = virtual_chassis.members.prefetch_related('rack').order_by('vc_position')
vc_form = forms.VirtualChassisForm(request.POST, instance=virtual_chassis)
2018-02-14 12:05:00 -05:00
vc_form.fields['master'].queryset = members_queryset
formset = VCMemberFormSet(request.POST, queryset=members_queryset)
if vc_form.is_valid() and formset.is_valid():
2018-02-01 15:53:59 -05:00
with transaction.atomic():
# Save the VirtualChassis
vc_form.save()
# Nullify the vc_position of each member first to allow reordering without raising an IntegrityError on
# duplicate positions. Then save each member instance.
members = formset.save(commit=False)
2019-08-20 17:16:00 -04:00
devices = Device.objects.filter(pk__in=[m.pk for m in members])
for device in devices:
device.vc_position = None
device.save()
2018-02-01 15:53:59 -05:00
for member in members:
member.save()
return redirect(virtual_chassis.get_absolute_url())
2018-02-01 11:39:13 -05:00
return render(request, 'dcim/virtualchassis_edit.html', {
'vc_form': vc_form,
'formset': formset,
'return_url': self.get_return_url(request, virtual_chassis),
})
class VirtualChassisDeleteView(ObjectDeleteView):
queryset = VirtualChassis.objects.all()
2018-02-01 11:39:13 -05:00
class VirtualChassisAddMemberView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
queryset = VirtualChassis.objects.all()
def get_required_permission(self):
return 'dcim.change_virtualchassis'
2018-02-01 11:39:13 -05:00
def get(self, request, pk):
virtual_chassis = get_object_or_404(self.queryset, pk=pk)
2018-02-01 11:39:13 -05:00
initial_data = {k: request.GET[k] for k in request.GET}
member_select_form = forms.VCMemberSelectForm(initial=initial_data)
membership_form = forms.DeviceVCMembershipForm(initial=initial_data)
return render(request, 'dcim/virtualchassis_add_member.html', {
'virtual_chassis': virtual_chassis,
'member_select_form': member_select_form,
'membership_form': membership_form,
'return_url': self.get_return_url(request, virtual_chassis),
})
def post(self, request, pk):
virtual_chassis = get_object_or_404(self.queryset, pk=pk)
2018-02-01 11:39:13 -05:00
member_select_form = forms.VCMemberSelectForm(request.POST)
if member_select_form.is_valid():
device = member_select_form.cleaned_data['device']
device.virtual_chassis = virtual_chassis
data = {k: request.POST[k] for k in ['vc_position', 'vc_priority']}
membership_form = forms.DeviceVCMembershipForm(data=data, validate_vc_position=True, instance=device)
2018-02-01 11:39:13 -05:00
if membership_form.is_valid():
membership_form.save()
msg = 'Added member <a href="{}">{}</a>'.format(device.get_absolute_url(), escape(device))
messages.success(request, mark_safe(msg))
if '_addanother' in request.POST:
return redirect(request.get_full_path())
return redirect(self.get_return_url(request, device))
else:
membership_form = forms.DeviceVCMembershipForm(data=request.POST)
2018-02-01 11:39:13 -05:00
return render(request, 'dcim/virtualchassis_add_member.html', {
'virtual_chassis': virtual_chassis,
'member_select_form': member_select_form,
'membership_form': membership_form,
'return_url': self.get_return_url(request, virtual_chassis),
})
class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
queryset = Device.objects.all()
def get_required_permission(self):
return 'dcim.change_device'
def get(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk, virtual_chassis__isnull=False)
form = ConfirmationForm(initial=request.GET)
return render(request, 'dcim/virtualchassis_remove_member.html', {
'device': device,
'form': form,
'return_url': self.get_return_url(request, device),
})
def post(self, request, pk):
device = get_object_or_404(self.queryset, pk=pk, virtual_chassis__isnull=False)
form = ConfirmationForm(request.POST)
# Protect master device from being removed
virtual_chassis = VirtualChassis.objects.filter(master=device).first()
if virtual_chassis is not None:
msg = 'Unable to remove master device {} from the virtual chassis.'.format(escape(device))
messages.error(request, mark_safe(msg))
return redirect(device.get_absolute_url())
if form.is_valid():
2019-08-20 17:16:00 -04:00
devices = Device.objects.filter(pk=device.pk)
for device in devices:
device.virtual_chassis = None
device.vc_position = None
device.vc_priority = None
device.save()
msg = 'Removed {} from virtual chassis {}'.format(device, device.virtual_chassis)
messages.success(request, msg)
return redirect(self.get_return_url(request, device))
return render(request, 'dcim/virtualchassis_remove_member.html', {
'device': device,
'form': form,
'return_url': self.get_return_url(request, device),
})
2019-03-11 22:40:52 -04:00
2020-06-24 15:29:25 -04:00
class VirtualChassisBulkImportView(BulkImportView):
queryset = VirtualChassis.objects.all()
model_form = forms.VirtualChassisCSVForm
table = tables.VirtualChassisTable
class VirtualChassisBulkEditView(BulkEditView):
queryset = VirtualChassis.objects.all()
filterset = filters.VirtualChassisFilterSet
table = tables.VirtualChassisTable
form = forms.VirtualChassisBulkEditForm
class VirtualChassisBulkDeleteView(BulkDeleteView):
queryset = VirtualChassis.objects.all()
filterset = filters.VirtualChassisFilterSet
table = tables.VirtualChassisTable
2019-03-11 22:40:52 -04:00
#
# Power panels
#
class PowerPanelListView(ObjectListView):
queryset = PowerPanel.objects.prefetch_related(
2019-03-12 11:36:29 -04:00
'site', 'rack_group'
2019-03-11 22:40:52 -04:00
).annotate(
2019-03-12 11:36:29 -04:00
powerfeed_count=Count('powerfeeds')
2019-03-11 22:40:52 -04:00
)
filterset = filters.PowerPanelFilterSet
filterset_form = forms.PowerPanelFilterForm
2019-03-11 22:40:52 -04:00
table = tables.PowerPanelTable
class PowerPanelView(ObjectView):
queryset = PowerPanel.objects.prefetch_related('site', 'rack_group')
2019-03-12 10:15:56 -04:00
def get(self, request, pk):
powerpanel = get_object_or_404(self.queryset, pk=pk)
power_feeds = PowerFeed.objects.restrict(request.user).filter(power_panel=powerpanel).prefetch_related('rack')
2019-03-22 21:58:45 -04:00
powerfeed_table = tables.PowerFeedTable(
data=power_feeds,
2019-03-22 21:58:45 -04:00
orderable=False
)
powerfeed_table.exclude = ['power_panel']
2019-03-12 10:15:56 -04:00
return render(request, 'dcim/powerpanel.html', {
'powerpanel': powerpanel,
2019-03-22 21:58:45 -04:00
'powerfeed_table': powerfeed_table,
2019-03-12 10:15:56 -04:00
})
class PowerPanelEditView(ObjectEditView):
queryset = PowerPanel.objects.all()
2019-03-11 22:40:52 -04:00
model_form = forms.PowerPanelForm
class PowerPanelDeleteView(ObjectDeleteView):
queryset = PowerPanel.objects.all()
2019-03-12 10:15:56 -04:00
class PowerPanelBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = PowerPanel.objects.all()
2019-03-11 22:40:52 -04:00
model_form = forms.PowerPanelCSVForm
table = tables.PowerPanelTable
class PowerPanelBulkEditView(BulkEditView):
queryset = PowerPanel.objects.prefetch_related('site', 'rack_group')
filterset = filters.PowerPanelFilterSet
table = tables.PowerPanelTable
form = forms.PowerPanelBulkEditForm
class PowerPanelBulkDeleteView(BulkDeleteView):
queryset = PowerPanel.objects.prefetch_related(
2019-03-11 22:40:52 -04:00
'site', 'rack_group'
).annotate(
rack_count=Count('powerfeeds')
)
filterset = filters.PowerPanelFilterSet
2019-03-11 22:40:52 -04:00
table = tables.PowerPanelTable
#
# Power feeds
#
class PowerFeedListView(ObjectListView):
queryset = PowerFeed.objects.prefetch_related(
2019-03-12 11:36:29 -04:00
'power_panel', 'rack'
2019-03-11 22:40:52 -04:00
)
filterset = filters.PowerFeedFilterSet
filterset_form = forms.PowerFeedFilterForm
2019-03-11 22:40:52 -04:00
table = tables.PowerFeedTable
class PowerFeedView(ObjectView):
queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack')
2019-03-11 22:40:52 -04:00
def get(self, request, pk):
powerfeed = get_object_or_404(self.queryset, pk=pk)
2019-03-11 22:40:52 -04:00
return render(request, 'dcim/powerfeed.html', {
'powerfeed': powerfeed,
})
class PowerFeedEditView(ObjectEditView):
queryset = PowerFeed.objects.all()
2019-03-11 22:40:52 -04:00
model_form = forms.PowerFeedForm
template_name = 'dcim/powerfeed_edit.html'
class PowerFeedDeleteView(ObjectDeleteView):
queryset = PowerFeed.objects.all()
2019-03-11 22:40:52 -04:00
class PowerFeedBulkImportView(BulkImportView):
2020-05-21 11:58:27 -04:00
queryset = PowerFeed.objects.all()
2019-03-11 22:40:52 -04:00
model_form = forms.PowerFeedCSVForm
table = tables.PowerFeedTable
class PowerFeedBulkEditView(BulkEditView):
queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack')
filterset = filters.PowerFeedFilterSet
2019-03-11 22:40:52 -04:00
table = tables.PowerFeedTable
form = forms.PowerFeedBulkEditForm
class PowerFeedBulkDeleteView(BulkDeleteView):
queryset = PowerFeed.objects.prefetch_related('power_panel', 'rack')
filterset = filters.PowerFeedFilterSet
2019-03-11 22:40:52 -04:00
table = tables.PowerFeedTable