import traceback from django.contrib import messages from django.contrib.contenttypes.models import ContentType from django.core.paginator import EmptyPage, PageNotAnInteger from django.db import transaction from django.db.models import Prefetch from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory from django.http import HttpResponse 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.utils.translation import gettext as _ from django.views.generic import View from jinja2.exceptions import TemplateError from circuits.models import Circuit, CircuitTermination from extras.views import ObjectConfigContextView from ipam.models import ASN, IPAddress, Prefix, VLAN, VLANGroup from ipam.tables import InterfaceVLANTable from netbox.constants import DEFAULT_ACTION_PERMISSIONS from netbox.views import generic from tenancy.views import ObjectContactsView from utilities.forms import ConfirmationForm from utilities.paginator import EnhancedPaginator, get_paginate_count from utilities.permissions import get_permission_for_model from utilities.query_functions import CollateAsChar from utilities.utils import count_related from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin, ViewTab, register_model_view from virtualization.models import VirtualMachine from . import filtersets, forms, tables from .choices import DeviceFaceChoices from .models import * CABLE_TERMINATION_TYPES = { 'dcim.consoleport': ConsolePort, 'dcim.consoleserverport': ConsoleServerPort, 'dcim.powerport': PowerPort, 'dcim.poweroutlet': PowerOutlet, 'dcim.interface': Interface, 'dcim.frontport': FrontPort, 'dcim.rearport': RearPort, 'dcim.powerfeed': PowerFeed, 'circuits.circuittermination': CircuitTermination, } class DeviceComponentsView(generic.ObjectChildrenView): actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, 'bulk_disconnect': {'change'}, } queryset = Device.objects.all() def get_children(self, request, parent): return self.child_model.objects.restrict(request.user, 'view').filter(device=parent) class DeviceTypeComponentsView(generic.ObjectChildrenView): actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } queryset = DeviceType.objects.all() template_name = 'dcim/devicetype/component_templates.html' viewname = None # Used for return_url resolution def get_children(self, request, parent): return self.child_model.objects.restrict(request.user, 'view').filter(device_type=parent) def get_extra_context(self, request, instance): return { 'return_url': reverse(self.viewname, kwargs={'pk': instance.pk}), } class ModuleTypeComponentsView(DeviceComponentsView): queryset = ModuleType.objects.all() template_name = 'dcim/moduletype/component_templates.html' viewname = None # Used for return_url resolution def get_children(self, request, parent): return self.child_model.objects.restrict(request.user, 'view').filter(module_type=parent) def get_extra_context(self, request, instance): return { 'return_url': reverse(self.viewname, kwargs={'pk': instance.pk}), } 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 cable_ids = set() for obj in self.queryset.filter(pk__in=form.cleaned_data['pk']): if obj.cable: cable_ids.add(obj.cable.pk) count += 1 for cable in Cable.objects.filter(pk__in=cable_ids): cable.delete() messages.success(request, _("Disconnected {count} {type}").format( count=count, type=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, }) class PathTraceView(generic.ObjectView): """ Trace a cable path beginning from the given path endpoint (origin). """ additional_permissions = ['dcim.view_cable'] template_name = 'dcim/cable_trace.html' def dispatch(self, request, *args, **kwargs): model = kwargs.pop('model') self.queryset = model.objects.all() return super().dispatch(request, *args, **kwargs) def get_extra_context(self, request, instance): related_paths = [] # If tracing a PathEndpoint, locate the CablePath (if one exists) by its origin if isinstance(instance, PathEndpoint): path = instance._path # Otherwise, find all CablePaths which traverse the specified object else: related_paths = CablePath.objects.filter(_nodes__contains=instance) # Check for specification of a particular path (when tracing pass-through ports) try: path_id = int(request.GET.get('cablepath_id')) except TypeError: path_id = None if path_id in list(related_paths.values_list('pk', flat=True)): path = CablePath.objects.get(pk=path_id) else: path = related_paths.first() # No paths found if path is None: return { 'path': None } # Get the total length of the cable and whether the length is definitive (fully defined) total_length, is_definitive = path.get_total_length() if path else (None, False) # Determine the path to the SVG trace image api_viewname = f"{path.origin_type.app_label}-api:{path.origin_type.model}-trace" svg_url = f"{reverse(api_viewname, kwargs={'pk': path.origins[0].pk})}?render=svg" return { 'path': path, 'related_paths': related_paths, 'total_length': total_length, 'is_definitive': is_definitive, 'svg_url': svg_url, } # # Regions # class RegionListView(generic.ObjectListView): queryset = Region.objects.add_related_count( Region.objects.all(), Site, 'region', 'site_count', cumulative=True ) filterset = filtersets.RegionFilterSet filterset_form = forms.RegionFilterForm table = tables.RegionTable @register_model_view(Region) class RegionView(generic.ObjectView): queryset = Region.objects.all() def get_extra_context(self, request, instance): regions = instance.get_descendants(include_self=True) related_models = ( (Site.objects.restrict(request.user, 'view').filter(region__in=regions), 'region_id'), (Location.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), (Rack.objects.restrict(request.user, 'view').filter(site__region__in=regions), 'region_id'), ) return { 'related_models': related_models, } @register_model_view(Region, 'edit') class RegionEditView(generic.ObjectEditView): queryset = Region.objects.all() form = forms.RegionForm @register_model_view(Region, 'delete') class RegionDeleteView(generic.ObjectDeleteView): queryset = Region.objects.all() class RegionBulkImportView(generic.BulkImportView): queryset = Region.objects.all() model_form = forms.RegionImportForm class RegionBulkEditView(generic.BulkEditView): queryset = Region.objects.add_related_count( Region.objects.all(), Site, 'region', 'site_count', cumulative=True ) filterset = filtersets.RegionFilterSet table = tables.RegionTable form = forms.RegionBulkEditForm class RegionBulkDeleteView(generic.BulkDeleteView): queryset = Region.objects.add_related_count( Region.objects.all(), Site, 'region', 'site_count', cumulative=True ) filterset = filtersets.RegionFilterSet table = tables.RegionTable @register_model_view(Region, 'contacts') class RegionContactsView(ObjectContactsView): queryset = Region.objects.all() # # Site groups # class SiteGroupListView(generic.ObjectListView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), Site, 'group', 'site_count', cumulative=True ) filterset = filtersets.SiteGroupFilterSet filterset_form = forms.SiteGroupFilterForm table = tables.SiteGroupTable @register_model_view(SiteGroup) class SiteGroupView(generic.ObjectView): queryset = SiteGroup.objects.all() def get_extra_context(self, request, instance): groups = instance.get_descendants(include_self=True) related_models = ( (Site.objects.restrict(request.user, 'view').filter(group__in=groups), 'group_id'), (Location.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), (Rack.objects.restrict(request.user, 'view').filter(site__group__in=groups), 'site_group_id'), ) return { 'related_models': related_models, } @register_model_view(SiteGroup, 'edit') class SiteGroupEditView(generic.ObjectEditView): queryset = SiteGroup.objects.all() form = forms.SiteGroupForm @register_model_view(SiteGroup, 'delete') class SiteGroupDeleteView(generic.ObjectDeleteView): queryset = SiteGroup.objects.all() class SiteGroupBulkImportView(generic.BulkImportView): queryset = SiteGroup.objects.all() model_form = forms.SiteGroupImportForm class SiteGroupBulkEditView(generic.BulkEditView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), Site, 'group', 'site_count', cumulative=True ) filterset = filtersets.SiteGroupFilterSet table = tables.SiteGroupTable form = forms.SiteGroupBulkEditForm class SiteGroupBulkDeleteView(generic.BulkDeleteView): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), Site, 'group', 'site_count', cumulative=True ) filterset = filtersets.SiteGroupFilterSet table = tables.SiteGroupTable @register_model_view(SiteGroup, 'contacts') class SiteGroupContactsView(ObjectContactsView): queryset = SiteGroup.objects.all() # # Sites # class SiteListView(generic.ObjectListView): queryset = Site.objects.all() filterset = filtersets.SiteFilterSet filterset_form = forms.SiteFilterForm table = tables.SiteTable @register_model_view(Site) class SiteView(generic.ObjectView): queryset = Site.objects.prefetch_related('tenant__group') def get_extra_context(self, request, instance): related_models = ( # DCIM (Location.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'), (Rack.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'), (Device.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'), # Virtualization (VirtualMachine.objects.restrict(request.user, 'view').filter(cluster__site=instance), 'site_id'), # IPAM (Prefix.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'), (ASN.objects.restrict(request.user, 'view').filter(sites=instance), 'site_id'), (VLANGroup.objects.restrict(request.user, 'view').filter( scope_type=ContentType.objects.get_for_model(Site), scope_id=instance.pk ), 'site'), (VLAN.objects.restrict(request.user, 'view').filter(site=instance), 'site_id'), # Circuits (Circuit.objects.restrict(request.user, 'view').filter(terminations__site=instance).distinct(), 'site_id'), ) return { 'related_models': related_models, } @register_model_view(Site, 'edit') class SiteEditView(generic.ObjectEditView): queryset = Site.objects.all() form = forms.SiteForm @register_model_view(Site, 'delete') class SiteDeleteView(generic.ObjectDeleteView): queryset = Site.objects.all() class SiteBulkImportView(generic.BulkImportView): queryset = Site.objects.all() model_form = forms.SiteImportForm class SiteBulkEditView(generic.BulkEditView): queryset = Site.objects.all() filterset = filtersets.SiteFilterSet table = tables.SiteTable form = forms.SiteBulkEditForm class SiteBulkDeleteView(generic.BulkDeleteView): queryset = Site.objects.all() filterset = filtersets.SiteFilterSet table = tables.SiteTable @register_model_view(Site, 'contacts') class SiteContactsView(ObjectContactsView): queryset = Site.objects.all() # # Locations # class LocationListView(generic.ObjectListView): queryset = Location.objects.add_related_count( Location.objects.add_related_count( Location.objects.all(), Device, 'location', 'device_count', cumulative=True ), Rack, 'location', 'rack_count', cumulative=True ) filterset = filtersets.LocationFilterSet filterset_form = forms.LocationFilterForm table = tables.LocationTable @register_model_view(Location) class LocationView(generic.ObjectView): queryset = Location.objects.all() def get_extra_context(self, request, instance): locations = instance.get_descendants(include_self=True) related_models = ( (Rack.objects.restrict(request.user, 'view').filter(location__in=locations), 'location_id'), (Device.objects.restrict(request.user, 'view').filter(location__in=locations), 'location_id'), ) return { 'related_models': related_models, } @register_model_view(Location, 'edit') class LocationEditView(generic.ObjectEditView): queryset = Location.objects.all() form = forms.LocationForm @register_model_view(Location, 'delete') class LocationDeleteView(generic.ObjectDeleteView): queryset = Location.objects.all() class LocationBulkImportView(generic.BulkImportView): queryset = Location.objects.all() model_form = forms.LocationImportForm class LocationBulkEditView(generic.BulkEditView): queryset = Location.objects.add_related_count( Location.objects.all(), Rack, 'location', 'rack_count', cumulative=True ).prefetch_related('site') filterset = filtersets.LocationFilterSet table = tables.LocationTable form = forms.LocationBulkEditForm class LocationBulkDeleteView(generic.BulkDeleteView): queryset = Location.objects.add_related_count( Location.objects.all(), Rack, 'location', 'rack_count', cumulative=True ).prefetch_related('site') filterset = filtersets.LocationFilterSet table = tables.LocationTable @register_model_view(Location, 'contacts') class LocationContactsView(ObjectContactsView): queryset = Location.objects.all() # # Rack roles # class RackRoleListView(generic.ObjectListView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') ) filterset = filtersets.RackRoleFilterSet filterset_form = forms.RackRoleFilterForm table = tables.RackRoleTable @register_model_view(RackRole) class RackRoleView(generic.ObjectView): queryset = RackRole.objects.all() def get_extra_context(self, request, instance): related_models = ( (Rack.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'), ) return { 'related_models': related_models, } @register_model_view(RackRole, 'edit') class RackRoleEditView(generic.ObjectEditView): queryset = RackRole.objects.all() form = forms.RackRoleForm @register_model_view(RackRole, 'delete') class RackRoleDeleteView(generic.ObjectDeleteView): queryset = RackRole.objects.all() class RackRoleBulkImportView(generic.BulkImportView): queryset = RackRole.objects.all() model_form = forms.RackRoleImportForm class RackRoleBulkEditView(generic.BulkEditView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') ) filterset = filtersets.RackRoleFilterSet table = tables.RackRoleTable form = forms.RackRoleBulkEditForm class RackRoleBulkDeleteView(generic.BulkDeleteView): queryset = RackRole.objects.annotate( rack_count=count_related(Rack, 'role') ) filterset = filtersets.RackRoleFilterSet table = tables.RackRoleTable # # Racks # class RackListView(generic.ObjectListView): queryset = Rack.objects.annotate( device_count=count_related(Device, 'rack') ) filterset = filtersets.RackFilterSet filterset_form = forms.RackFilterForm table = tables.RackTable template_name = 'dcim/rack_list.html' class RackElevationListView(generic.ObjectListView): """ Display a set of rack elevations side-by-side. """ queryset = Rack.objects.prefetch_related('role') def get(self, request): racks = filtersets.RackFilterSet(request.GET, self.queryset).qs total_count = racks.count() # Ordering ORDERING_CHOICES = { 'name': 'Name (A-Z)', '-name': 'Name (Z-A)', 'facility_id': 'Facility ID (A-Z)', '-facility_id': 'Facility ID (Z-A)', } sort = request.GET.get('sort', 'name') if sort not in ORDERING_CHOICES: sort = 'name' sort_field = sort.replace("name", "_name") # Use natural ordering racks = racks.order_by(sort_field) # Pagination per_page = get_paginate_count(request) 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, 'sort': sort, 'sort_display_name': ORDERING_CHOICES[sort], 'sort_choices': ORDERING_CHOICES, 'rack_face': rack_face, 'filter_form': forms.RackElevationFilterForm(request.GET), 'model': self.queryset.model, }) @register_model_view(Rack) class RackView(generic.ObjectView): queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role') def get_extra_context(self, request, instance): related_models = ( (Device.objects.restrict(request.user, 'view').filter(rack=instance), 'rack_id'), (PowerFeed.objects.restrict(request.user).filter(rack=instance), 'rack_id'), ) peer_racks = Rack.objects.restrict(request.user, 'view').filter(site=instance.site) if instance.location: peer_racks = peer_racks.filter(location=instance.location) else: peer_racks = peer_racks.filter(location__isnull=True) next_rack = peer_racks.filter(_name__gt=instance._name).first() prev_rack = peer_racks.filter(_name__lt=instance._name).reverse().first() # Determine any additional parameters to pass when embedding the rack elevations svg_extra = '&'.join([ f'highlight=id:{pk}' for pk in request.GET.getlist('device') ]) return { 'related_models': related_models, 'next_rack': next_rack, 'prev_rack': prev_rack, 'svg_extra': svg_extra, 'peer_racks': peer_racks, } @register_model_view(Rack, 'reservations') class RackRackReservationsView(generic.ObjectChildrenView): queryset = Rack.objects.all() child_model = RackReservation table = tables.RackReservationTable filterset = filtersets.RackReservationFilterSet template_name = 'dcim/rack/reservations.html' tab = ViewTab( label=_('Reservations'), badge=lambda obj: obj.reservations.count(), permission='dcim.view_rackreservation', weight=510 ) def get_children(self, request, parent): return parent.reservations.restrict(request.user, 'view') @register_model_view(Rack, 'nonracked_devices', 'nonracked-devices') class RackNonRackedView(generic.ObjectChildrenView): queryset = Rack.objects.all() child_model = Device table = tables.DeviceTable filterset = filtersets.DeviceFilterSet template_name = 'dcim/rack/non_racked_devices.html' tab = ViewTab( label=_('Non-Racked Devices'), badge=lambda obj: obj.devices.filter(rack=obj, position__isnull=True, parent_bay__isnull=True).count(), weight=500, permission='dcim.view_device', ) def get_children(self, request, parent): return parent.devices.restrict(request.user, 'view').filter( rack=parent, position__isnull=True, parent_bay__isnull=True ) @register_model_view(Rack, 'edit') class RackEditView(generic.ObjectEditView): queryset = Rack.objects.all() form = forms.RackForm @register_model_view(Rack, 'delete') class RackDeleteView(generic.ObjectDeleteView): queryset = Rack.objects.all() class RackBulkImportView(generic.BulkImportView): queryset = Rack.objects.all() model_form = forms.RackImportForm class RackBulkEditView(generic.BulkEditView): queryset = Rack.objects.all() filterset = filtersets.RackFilterSet table = tables.RackTable form = forms.RackBulkEditForm class RackBulkDeleteView(generic.BulkDeleteView): queryset = Rack.objects.all() filterset = filtersets.RackFilterSet table = tables.RackTable @register_model_view(Rack, 'contacts') class RackContactsView(ObjectContactsView): queryset = Rack.objects.all() # # Rack reservations # class RackReservationListView(generic.ObjectListView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet filterset_form = forms.RackReservationFilterForm table = tables.RackReservationTable @register_model_view(RackReservation) class RackReservationView(generic.ObjectView): queryset = RackReservation.objects.all() @register_model_view(RackReservation, 'edit') class RackReservationEditView(generic.ObjectEditView): queryset = RackReservation.objects.all() form = forms.RackReservationForm def alter_object(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 @register_model_view(RackReservation, 'delete') class RackReservationDeleteView(generic.ObjectDeleteView): queryset = RackReservation.objects.all() class RackReservationImportView(generic.BulkImportView): queryset = RackReservation.objects.all() model_form = forms.RackReservationImportForm def save_object(self, object_form, request): """ Assign the currently authenticated user to the RackReservation. """ instance = object_form.save(commit=False) instance.user = request.user instance.save() return instance class RackReservationBulkEditView(generic.BulkEditView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet table = tables.RackReservationTable form = forms.RackReservationBulkEditForm class RackReservationBulkDeleteView(generic.BulkDeleteView): queryset = RackReservation.objects.all() filterset = filtersets.RackReservationFilterSet table = tables.RackReservationTable # # Manufacturers # class ManufacturerListView(generic.ObjectListView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), moduletype_count=count_related(ModuleType, 'manufacturer'), inventoryitem_count=count_related(InventoryItem, 'manufacturer'), platform_count=count_related(Platform, 'manufacturer') ) filterset = filtersets.ManufacturerFilterSet filterset_form = forms.ManufacturerFilterForm table = tables.ManufacturerTable @register_model_view(Manufacturer) class ManufacturerView(generic.ObjectView): queryset = Manufacturer.objects.all() def get_extra_context(self, request, instance): related_models = ( (DeviceType.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'), (ModuleType.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'), (InventoryItem.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'), (Platform.objects.restrict(request.user, 'view').filter(manufacturer=instance), 'manufacturer_id'), ) return { 'related_models': related_models, } @register_model_view(Manufacturer, 'edit') class ManufacturerEditView(generic.ObjectEditView): queryset = Manufacturer.objects.all() form = forms.ManufacturerForm @register_model_view(Manufacturer, 'delete') class ManufacturerDeleteView(generic.ObjectDeleteView): queryset = Manufacturer.objects.all() class ManufacturerBulkImportView(generic.BulkImportView): queryset = Manufacturer.objects.all() model_form = forms.ManufacturerImportForm class ManufacturerBulkEditView(generic.BulkEditView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), moduletype_count=count_related(ModuleType, 'manufacturer'), inventoryitem_count=count_related(InventoryItem, 'manufacturer'), platform_count=count_related(Platform, 'manufacturer') ) filterset = filtersets.ManufacturerFilterSet table = tables.ManufacturerTable form = forms.ManufacturerBulkEditForm class ManufacturerBulkDeleteView(generic.BulkDeleteView): queryset = Manufacturer.objects.annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), moduletype_count=count_related(ModuleType, 'manufacturer'), inventoryitem_count=count_related(InventoryItem, 'manufacturer'), platform_count=count_related(Platform, 'manufacturer') ) filterset = filtersets.ManufacturerFilterSet table = tables.ManufacturerTable @register_model_view(Manufacturer, 'contacts') class ManufacturerContactsView(ObjectContactsView): queryset = Manufacturer.objects.all() # # Device types # class DeviceTypeListView(generic.ObjectListView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') ) filterset = filtersets.DeviceTypeFilterSet filterset_form = forms.DeviceTypeFilterForm table = tables.DeviceTypeTable @register_model_view(DeviceType) class DeviceTypeView(generic.ObjectView): queryset = DeviceType.objects.all() def get_extra_context(self, request, instance): related_models = ( (Device.objects.restrict(request.user).filter(device_type=instance), 'device_type_id'), ) return { 'related_models': related_models, } @register_model_view(DeviceType, 'edit') class DeviceTypeEditView(generic.ObjectEditView): queryset = DeviceType.objects.all() form = forms.DeviceTypeForm @register_model_view(DeviceType, 'delete') class DeviceTypeDeleteView(generic.ObjectDeleteView): queryset = DeviceType.objects.all() @register_model_view(DeviceType, 'consoleports', path='console-ports') class DeviceTypeConsolePortsView(DeviceTypeComponentsView): child_model = ConsolePortTemplate table = tables.ConsolePortTemplateTable filterset = filtersets.ConsolePortTemplateFilterSet viewname = 'dcim:devicetype_consoleports' tab = ViewTab( label=_('Console Ports'), badge=lambda obj: obj.console_port_template_count, permission='dcim.view_consoleporttemplate', weight=550, hide_if_empty=True ) @register_model_view(DeviceType, 'consoleserverports', path='console-server-ports') class DeviceTypeConsoleServerPortsView(DeviceTypeComponentsView): child_model = ConsoleServerPortTemplate table = tables.ConsoleServerPortTemplateTable filterset = filtersets.ConsoleServerPortTemplateFilterSet viewname = 'dcim:devicetype_consoleserverports' tab = ViewTab( label=_('Console Server Ports'), badge=lambda obj: obj.console_server_port_template_count, permission='dcim.view_consoleserverporttemplate', weight=560, hide_if_empty=True ) @register_model_view(DeviceType, 'powerports', path='power-ports') class DeviceTypePowerPortsView(DeviceTypeComponentsView): child_model = PowerPortTemplate table = tables.PowerPortTemplateTable filterset = filtersets.PowerPortTemplateFilterSet viewname = 'dcim:devicetype_powerports' tab = ViewTab( label=_('Power Ports'), badge=lambda obj: obj.power_port_template_count, permission='dcim.view_powerporttemplate', weight=570, hide_if_empty=True ) @register_model_view(DeviceType, 'poweroutlets', path='power-outlets') class DeviceTypePowerOutletsView(DeviceTypeComponentsView): child_model = PowerOutletTemplate table = tables.PowerOutletTemplateTable filterset = filtersets.PowerOutletTemplateFilterSet viewname = 'dcim:devicetype_poweroutlets' tab = ViewTab( label=_('Power Outlets'), badge=lambda obj: obj.power_outlet_template_count, permission='dcim.view_poweroutlettemplate', weight=580, hide_if_empty=True ) @register_model_view(DeviceType, 'interfaces') class DeviceTypeInterfacesView(DeviceTypeComponentsView): child_model = InterfaceTemplate table = tables.InterfaceTemplateTable filterset = filtersets.InterfaceTemplateFilterSet viewname = 'dcim:devicetype_interfaces' tab = ViewTab( label=_('Interfaces'), badge=lambda obj: obj.interface_template_count, permission='dcim.view_interfacetemplate', weight=520, hide_if_empty=True ) @register_model_view(DeviceType, 'frontports', path='front-ports') class DeviceTypeFrontPortsView(DeviceTypeComponentsView): child_model = FrontPortTemplate table = tables.FrontPortTemplateTable filterset = filtersets.FrontPortTemplateFilterSet viewname = 'dcim:devicetype_frontports' tab = ViewTab( label=_('Front Ports'), badge=lambda obj: obj.front_port_template_count, permission='dcim.view_frontporttemplate', weight=530, hide_if_empty=True ) @register_model_view(DeviceType, 'rearports', path='rear-ports') class DeviceTypeRearPortsView(DeviceTypeComponentsView): child_model = RearPortTemplate table = tables.RearPortTemplateTable filterset = filtersets.RearPortTemplateFilterSet viewname = 'dcim:devicetype_rearports' tab = ViewTab( label=_('Rear Ports'), badge=lambda obj: obj.rear_port_template_count, permission='dcim.view_rearporttemplate', weight=540, hide_if_empty=True ) @register_model_view(DeviceType, 'modulebays', path='module-bays') class DeviceTypeModuleBaysView(DeviceTypeComponentsView): child_model = ModuleBayTemplate table = tables.ModuleBayTemplateTable filterset = filtersets.ModuleBayTemplateFilterSet viewname = 'dcim:devicetype_modulebays' tab = ViewTab( label=_('Module Bays'), badge=lambda obj: obj.module_bay_template_count, permission='dcim.view_modulebaytemplate', weight=510, hide_if_empty=True ) @register_model_view(DeviceType, 'devicebays', path='device-bays') class DeviceTypeDeviceBaysView(DeviceTypeComponentsView): child_model = DeviceBayTemplate table = tables.DeviceBayTemplateTable filterset = filtersets.DeviceBayTemplateFilterSet viewname = 'dcim:devicetype_devicebays' tab = ViewTab( label=_('Device Bays'), badge=lambda obj: obj.device_bay_template_count, permission='dcim.view_devicebaytemplate', weight=500, hide_if_empty=True ) @register_model_view(DeviceType, 'inventoryitems', path='inventory-items') class DeviceTypeInventoryItemsView(DeviceTypeComponentsView): child_model = InventoryItemTemplate table = tables.InventoryItemTemplateTable filterset = filtersets.InventoryItemTemplateFilterSet viewname = 'dcim:devicetype_inventoryitems' tab = ViewTab( label=_('Inventory Items'), badge=lambda obj: obj.inventory_item_template_count, permission='dcim.view_inventoryitemtemplate', weight=590, hide_if_empty=True ) class DeviceTypeImportView(generic.BulkImportView): additional_permissions = [ '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_modulebaytemplate', 'dcim.add_devicebaytemplate', 'dcim.add_inventoryitemtemplate', ] queryset = DeviceType.objects.all() model_form = forms.DeviceTypeImportForm related_object_forms = { '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, 'module-bays': forms.ModuleBayTemplateImportForm, 'device-bays': forms.DeviceBayTemplateImportForm, 'inventory-items': forms.InventoryItemTemplateImportForm, } def prep_related_object_data(self, parent, data): data.update({'device_type': parent}) return data class DeviceTypeBulkEditView(generic.BulkEditView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') ) filterset = filtersets.DeviceTypeFilterSet table = tables.DeviceTypeTable form = forms.DeviceTypeBulkEditForm class DeviceTypeBulkDeleteView(generic.BulkDeleteView): queryset = DeviceType.objects.annotate( instance_count=count_related(Device, 'device_type') ) filterset = filtersets.DeviceTypeFilterSet table = tables.DeviceTypeTable # # Module types # class ModuleTypeListView(generic.ObjectListView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet filterset_form = forms.ModuleTypeFilterForm table = tables.ModuleTypeTable @register_model_view(ModuleType) class ModuleTypeView(generic.ObjectView): queryset = ModuleType.objects.all() def get_extra_context(self, request, instance): related_models = ( (Module.objects.restrict(request.user).filter(module_type=instance), 'module_type_id'), ) return { 'related_models': related_models, } @register_model_view(ModuleType, 'edit') class ModuleTypeEditView(generic.ObjectEditView): queryset = ModuleType.objects.all() form = forms.ModuleTypeForm @register_model_view(ModuleType, 'delete') class ModuleTypeDeleteView(generic.ObjectDeleteView): queryset = ModuleType.objects.all() @register_model_view(ModuleType, 'consoleports', path='console-ports') class ModuleTypeConsolePortsView(ModuleTypeComponentsView): child_model = ConsolePortTemplate table = tables.ConsolePortTemplateTable filterset = filtersets.ConsolePortTemplateFilterSet viewname = 'dcim:moduletype_consoleports' tab = ViewTab( label=_('Console Ports'), badge=lambda obj: obj.consoleporttemplates.count(), permission='dcim.view_consoleporttemplate', weight=530, hide_if_empty=True ) @register_model_view(ModuleType, 'consoleserverports', path='console-server-ports') class ModuleTypeConsoleServerPortsView(ModuleTypeComponentsView): child_model = ConsoleServerPortTemplate table = tables.ConsoleServerPortTemplateTable filterset = filtersets.ConsoleServerPortTemplateFilterSet viewname = 'dcim:moduletype_consoleserverports' tab = ViewTab( label=_('Console Server Ports'), badge=lambda obj: obj.consoleserverporttemplates.count(), permission='dcim.view_consoleserverporttemplate', weight=540, hide_if_empty=True ) @register_model_view(ModuleType, 'powerports', path='power-ports') class ModuleTypePowerPortsView(ModuleTypeComponentsView): child_model = PowerPortTemplate table = tables.PowerPortTemplateTable filterset = filtersets.PowerPortTemplateFilterSet viewname = 'dcim:moduletype_powerports' tab = ViewTab( label=_('Power Ports'), badge=lambda obj: obj.powerporttemplates.count(), permission='dcim.view_powerporttemplate', weight=550, hide_if_empty=True ) @register_model_view(ModuleType, 'poweroutlets', path='power-outlets') class ModuleTypePowerOutletsView(ModuleTypeComponentsView): child_model = PowerOutletTemplate table = tables.PowerOutletTemplateTable filterset = filtersets.PowerOutletTemplateFilterSet viewname = 'dcim:moduletype_poweroutlets' tab = ViewTab( label=_('Power Outlets'), badge=lambda obj: obj.poweroutlettemplates.count(), permission='dcim.view_poweroutlettemplate', weight=560, hide_if_empty=True ) @register_model_view(ModuleType, 'interfaces') class ModuleTypeInterfacesView(ModuleTypeComponentsView): child_model = InterfaceTemplate table = tables.InterfaceTemplateTable filterset = filtersets.InterfaceTemplateFilterSet viewname = 'dcim:moduletype_interfaces' tab = ViewTab( label=_('Interfaces'), badge=lambda obj: obj.interfacetemplates.count(), permission='dcim.view_interfacetemplate', weight=500, hide_if_empty=True ) @register_model_view(ModuleType, 'frontports', path='front-ports') class ModuleTypeFrontPortsView(ModuleTypeComponentsView): child_model = FrontPortTemplate table = tables.FrontPortTemplateTable filterset = filtersets.FrontPortTemplateFilterSet viewname = 'dcim:moduletype_frontports' tab = ViewTab( label=_('Front Ports'), badge=lambda obj: obj.frontporttemplates.count(), permission='dcim.view_frontporttemplate', weight=510, hide_if_empty=True ) @register_model_view(ModuleType, 'rearports', path='rear-ports') class ModuleTypeRearPortsView(ModuleTypeComponentsView): child_model = RearPortTemplate table = tables.RearPortTemplateTable filterset = filtersets.RearPortTemplateFilterSet viewname = 'dcim:moduletype_rearports' tab = ViewTab( label=_('Rear Ports'), badge=lambda obj: obj.rearporttemplates.count(), permission='dcim.view_rearporttemplate', weight=520, hide_if_empty=True ) class ModuleTypeImportView(generic.BulkImportView): additional_permissions = [ 'dcim.add_moduletype', 'dcim.add_consoleporttemplate', 'dcim.add_consoleserverporttemplate', 'dcim.add_powerporttemplate', 'dcim.add_poweroutlettemplate', 'dcim.add_interfacetemplate', 'dcim.add_frontporttemplate', 'dcim.add_rearporttemplate', ] queryset = ModuleType.objects.all() model_form = forms.ModuleTypeImportForm related_object_forms = { '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, } def prep_related_object_data(self, parent, data): data.update({'module_type': parent}) return data class ModuleTypeBulkEditView(generic.BulkEditView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet table = tables.ModuleTypeTable form = forms.ModuleTypeBulkEditForm class ModuleTypeBulkDeleteView(generic.BulkDeleteView): queryset = ModuleType.objects.annotate( instance_count=count_related(Module, 'module_type') ) filterset = filtersets.ModuleTypeFilterSet table = tables.ModuleTypeTable # # Console port templates # class ConsolePortTemplateCreateView(generic.ComponentCreateView): queryset = ConsolePortTemplate.objects.all() form = forms.ConsolePortTemplateCreateForm model_form = forms.ConsolePortTemplateForm @register_model_view(ConsolePortTemplate, 'edit') class ConsolePortTemplateEditView(generic.ObjectEditView): queryset = ConsolePortTemplate.objects.all() form = forms.ConsolePortTemplateForm @register_model_view(ConsolePortTemplate, 'delete') class ConsolePortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsolePortTemplate.objects.all() class ConsolePortTemplateBulkEditView(generic.BulkEditView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable form = forms.ConsolePortTemplateBulkEditForm class ConsolePortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsolePortTemplate.objects.all() class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePortTemplate.objects.all() table = tables.ConsolePortTemplateTable # # Console server port templates # class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView): queryset = ConsoleServerPortTemplate.objects.all() form = forms.ConsoleServerPortTemplateCreateForm model_form = forms.ConsoleServerPortTemplateForm @register_model_view(ConsoleServerPortTemplate, 'edit') class ConsoleServerPortTemplateEditView(generic.ObjectEditView): queryset = ConsoleServerPortTemplate.objects.all() form = forms.ConsoleServerPortTemplateForm @register_model_view(ConsoleServerPortTemplate, 'delete') class ConsoleServerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPortTemplate.objects.all() class ConsoleServerPortTemplateBulkEditView(generic.BulkEditView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable form = forms.ConsoleServerPortTemplateBulkEditForm class ConsoleServerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPortTemplate.objects.all() class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPortTemplate.objects.all() table = tables.ConsoleServerPortTemplateTable # # Power port templates # class PowerPortTemplateCreateView(generic.ComponentCreateView): queryset = PowerPortTemplate.objects.all() form = forms.PowerPortTemplateCreateForm model_form = forms.PowerPortTemplateForm @register_model_view(PowerPortTemplate, 'edit') class PowerPortTemplateEditView(generic.ObjectEditView): queryset = PowerPortTemplate.objects.all() form = forms.PowerPortTemplateForm @register_model_view(PowerPortTemplate, 'delete') class PowerPortTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerPortTemplate.objects.all() class PowerPortTemplateBulkEditView(generic.BulkEditView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable form = forms.PowerPortTemplateBulkEditForm class PowerPortTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerPortTemplate.objects.all() class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerPortTemplate.objects.all() table = tables.PowerPortTemplateTable # # Power outlet templates # class PowerOutletTemplateCreateView(generic.ComponentCreateView): queryset = PowerOutletTemplate.objects.all() form = forms.PowerOutletTemplateCreateForm model_form = forms.PowerOutletTemplateForm @register_model_view(PowerOutletTemplate, 'edit') class PowerOutletTemplateEditView(generic.ObjectEditView): queryset = PowerOutletTemplate.objects.all() form = forms.PowerOutletTemplateForm @register_model_view(PowerOutletTemplate, 'delete') class PowerOutletTemplateDeleteView(generic.ObjectDeleteView): queryset = PowerOutletTemplate.objects.all() class PowerOutletTemplateBulkEditView(generic.BulkEditView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable form = forms.PowerOutletTemplateBulkEditForm class PowerOutletTemplateBulkRenameView(generic.BulkRenameView): queryset = PowerOutletTemplate.objects.all() class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutletTemplate.objects.all() table = tables.PowerOutletTemplateTable # # Interface templates # class InterfaceTemplateCreateView(generic.ComponentCreateView): queryset = InterfaceTemplate.objects.all() form = forms.InterfaceTemplateCreateForm model_form = forms.InterfaceTemplateForm @register_model_view(InterfaceTemplate, 'edit') class InterfaceTemplateEditView(generic.ObjectEditView): queryset = InterfaceTemplate.objects.all() form = forms.InterfaceTemplateForm @register_model_view(InterfaceTemplate, 'delete') class InterfaceTemplateDeleteView(generic.ObjectDeleteView): queryset = InterfaceTemplate.objects.all() class InterfaceTemplateBulkEditView(generic.BulkEditView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable form = forms.InterfaceTemplateBulkEditForm class InterfaceTemplateBulkRenameView(generic.BulkRenameView): queryset = InterfaceTemplate.objects.all() class InterfaceTemplateBulkDeleteView(generic.BulkDeleteView): queryset = InterfaceTemplate.objects.all() table = tables.InterfaceTemplateTable # # Front port templates # class FrontPortTemplateCreateView(generic.ComponentCreateView): queryset = FrontPortTemplate.objects.all() form = forms.FrontPortTemplateCreateForm model_form = forms.FrontPortTemplateForm @register_model_view(FrontPortTemplate, 'edit') class FrontPortTemplateEditView(generic.ObjectEditView): queryset = FrontPortTemplate.objects.all() form = forms.FrontPortTemplateForm @register_model_view(FrontPortTemplate, 'delete') class FrontPortTemplateDeleteView(generic.ObjectDeleteView): queryset = FrontPortTemplate.objects.all() class FrontPortTemplateBulkEditView(generic.BulkEditView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable form = forms.FrontPortTemplateBulkEditForm class FrontPortTemplateBulkRenameView(generic.BulkRenameView): queryset = FrontPortTemplate.objects.all() class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = FrontPortTemplate.objects.all() table = tables.FrontPortTemplateTable # # Rear port templates # class RearPortTemplateCreateView(generic.ComponentCreateView): queryset = RearPortTemplate.objects.all() form = forms.RearPortTemplateCreateForm model_form = forms.RearPortTemplateForm @register_model_view(RearPortTemplate, 'edit') class RearPortTemplateEditView(generic.ObjectEditView): queryset = RearPortTemplate.objects.all() form = forms.RearPortTemplateForm @register_model_view(RearPortTemplate, 'delete') class RearPortTemplateDeleteView(generic.ObjectDeleteView): queryset = RearPortTemplate.objects.all() class RearPortTemplateBulkEditView(generic.BulkEditView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable form = forms.RearPortTemplateBulkEditForm class RearPortTemplateBulkRenameView(generic.BulkRenameView): queryset = RearPortTemplate.objects.all() class RearPortTemplateBulkDeleteView(generic.BulkDeleteView): queryset = RearPortTemplate.objects.all() table = tables.RearPortTemplateTable # # Module bay templates # class ModuleBayTemplateCreateView(generic.ComponentCreateView): queryset = ModuleBayTemplate.objects.all() form = forms.ModuleBayTemplateCreateForm model_form = forms.ModuleBayTemplateForm @register_model_view(ModuleBayTemplate, 'edit') class ModuleBayTemplateEditView(generic.ObjectEditView): queryset = ModuleBayTemplate.objects.all() form = forms.ModuleBayTemplateForm @register_model_view(ModuleBayTemplate, 'delete') class ModuleBayTemplateDeleteView(generic.ObjectDeleteView): queryset = ModuleBayTemplate.objects.all() class ModuleBayTemplateBulkEditView(generic.BulkEditView): queryset = ModuleBayTemplate.objects.all() table = tables.ModuleBayTemplateTable form = forms.ModuleBayTemplateBulkEditForm class ModuleBayTemplateBulkRenameView(generic.BulkRenameView): queryset = ModuleBayTemplate.objects.all() class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView): queryset = ModuleBayTemplate.objects.all() table = tables.ModuleBayTemplateTable # # Device bay templates # class DeviceBayTemplateCreateView(generic.ComponentCreateView): queryset = DeviceBayTemplate.objects.all() form = forms.DeviceBayTemplateCreateForm model_form = forms.DeviceBayTemplateForm @register_model_view(DeviceBayTemplate, 'edit') class DeviceBayTemplateEditView(generic.ObjectEditView): queryset = DeviceBayTemplate.objects.all() form = forms.DeviceBayTemplateForm @register_model_view(DeviceBayTemplate, 'delete') class DeviceBayTemplateDeleteView(generic.ObjectDeleteView): queryset = DeviceBayTemplate.objects.all() class DeviceBayTemplateBulkEditView(generic.BulkEditView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable form = forms.DeviceBayTemplateBulkEditForm class DeviceBayTemplateBulkRenameView(generic.BulkRenameView): queryset = DeviceBayTemplate.objects.all() class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBayTemplate.objects.all() table = tables.DeviceBayTemplateTable # # Inventory item templates # class InventoryItemTemplateCreateView(generic.ComponentCreateView): queryset = InventoryItemTemplate.objects.all() form = forms.InventoryItemTemplateCreateForm model_form = forms.InventoryItemTemplateForm def alter_object(self, instance, request): # Set component (if any) component_type = request.GET.get('component_type') component_id = request.GET.get('component_id') if component_type and component_id: content_type = get_object_or_404(ContentType, pk=component_type) instance.component = get_object_or_404(content_type.model_class(), pk=component_id) return instance @register_model_view(InventoryItemTemplate, 'edit') class InventoryItemTemplateEditView(generic.ObjectEditView): queryset = InventoryItemTemplate.objects.all() form = forms.InventoryItemTemplateForm @register_model_view(InventoryItemTemplate, 'delete') class InventoryItemTemplateDeleteView(generic.ObjectDeleteView): queryset = InventoryItemTemplate.objects.all() class InventoryItemTemplateBulkEditView(generic.BulkEditView): queryset = InventoryItemTemplate.objects.all() table = tables.InventoryItemTemplateTable form = forms.InventoryItemTemplateBulkEditForm class InventoryItemTemplateBulkRenameView(generic.BulkRenameView): queryset = InventoryItemTemplate.objects.all() class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItemTemplate.objects.all() table = tables.InventoryItemTemplateTable # # Device roles # class DeviceRoleListView(generic.ObjectListView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), vm_count=count_related(VirtualMachine, 'role') ) filterset = filtersets.DeviceRoleFilterSet filterset_form = forms.DeviceRoleFilterForm table = tables.DeviceRoleTable @register_model_view(DeviceRole) class DeviceRoleView(generic.ObjectView): queryset = DeviceRole.objects.all() def get_extra_context(self, request, instance): related_models = ( (Device.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'), (VirtualMachine.objects.restrict(request.user, 'view').filter(role=instance), 'role_id'), ) return { 'related_models': related_models, } @register_model_view(DeviceRole, 'edit') class DeviceRoleEditView(generic.ObjectEditView): queryset = DeviceRole.objects.all() form = forms.DeviceRoleForm @register_model_view(DeviceRole, 'delete') class DeviceRoleDeleteView(generic.ObjectDeleteView): queryset = DeviceRole.objects.all() class DeviceRoleBulkImportView(generic.BulkImportView): queryset = DeviceRole.objects.all() model_form = forms.DeviceRoleImportForm class DeviceRoleBulkEditView(generic.BulkEditView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), vm_count=count_related(VirtualMachine, 'role') ) filterset = filtersets.DeviceRoleFilterSet table = tables.DeviceRoleTable form = forms.DeviceRoleBulkEditForm class DeviceRoleBulkDeleteView(generic.BulkDeleteView): queryset = DeviceRole.objects.annotate( device_count=count_related(Device, 'role'), vm_count=count_related(VirtualMachine, 'role') ) filterset = filtersets.DeviceRoleFilterSet table = tables.DeviceRoleTable # # Platforms # class PlatformListView(generic.ObjectListView): queryset = Platform.objects.annotate( device_count=count_related(Device, 'platform'), vm_count=count_related(VirtualMachine, 'platform') ) table = tables.PlatformTable filterset = filtersets.PlatformFilterSet filterset_form = forms.PlatformFilterForm @register_model_view(Platform) class PlatformView(generic.ObjectView): queryset = Platform.objects.all() def get_extra_context(self, request, instance): related_models = ( (Device.objects.restrict(request.user, 'view').filter(platform=instance), 'platform_id'), (VirtualMachine.objects.restrict(request.user, 'view').filter(platform=instance), 'platform_id'), ) return { 'related_models': related_models, } @register_model_view(Platform, 'edit') class PlatformEditView(generic.ObjectEditView): queryset = Platform.objects.all() form = forms.PlatformForm @register_model_view(Platform, 'delete') class PlatformDeleteView(generic.ObjectDeleteView): queryset = Platform.objects.all() class PlatformBulkImportView(generic.BulkImportView): queryset = Platform.objects.all() model_form = forms.PlatformImportForm class PlatformBulkEditView(generic.BulkEditView): queryset = Platform.objects.all() filterset = filtersets.PlatformFilterSet table = tables.PlatformTable form = forms.PlatformBulkEditForm class PlatformBulkDeleteView(generic.BulkDeleteView): queryset = Platform.objects.all() filterset = filtersets.PlatformFilterSet table = tables.PlatformTable # # Devices # class DeviceListView(generic.ObjectListView): queryset = Device.objects.all() filterset = filtersets.DeviceFilterSet filterset_form = forms.DeviceFilterForm table = tables.DeviceTable template_name = 'dcim/device_list.html' @register_model_view(Device) class DeviceView(generic.ObjectView): queryset = Device.objects.all() def get_extra_context(self, request, instance): # VirtualChassis members if instance.virtual_chassis is not None: vc_members = Device.objects.restrict(request.user, 'view').filter( virtual_chassis=instance.virtual_chassis ).order_by('vc_position') else: vc_members = [] return { 'vc_members': vc_members, 'svg_extra': f'highlight=id:{instance.pk}' } @register_model_view(Device, 'edit') class DeviceEditView(generic.ObjectEditView): queryset = Device.objects.all() form = forms.DeviceForm template_name = 'dcim/device_edit.html' @register_model_view(Device, 'delete') class DeviceDeleteView(generic.ObjectDeleteView): queryset = Device.objects.all() @register_model_view(Device, 'consoleports', path='console-ports') class DeviceConsolePortsView(DeviceComponentsView): child_model = ConsolePort table = tables.DeviceConsolePortTable filterset = filtersets.ConsolePortFilterSet template_name = 'dcim/device/consoleports.html', tab = ViewTab( label=_('Console Ports'), badge=lambda obj: obj.console_port_count, permission='dcim.view_consoleport', weight=550, hide_if_empty=True ) @register_model_view(Device, 'consoleserverports', path='console-server-ports') class DeviceConsoleServerPortsView(DeviceComponentsView): child_model = ConsoleServerPort table = tables.DeviceConsoleServerPortTable filterset = filtersets.ConsoleServerPortFilterSet template_name = 'dcim/device/consoleserverports.html' tab = ViewTab( label=_('Console Server Ports'), badge=lambda obj: obj.console_server_port_count, permission='dcim.view_consoleserverport', weight=560, hide_if_empty=True ) @register_model_view(Device, 'powerports', path='power-ports') class DevicePowerPortsView(DeviceComponentsView): child_model = PowerPort table = tables.DevicePowerPortTable filterset = filtersets.PowerPortFilterSet template_name = 'dcim/device/powerports.html' tab = ViewTab( label=_('Power Ports'), badge=lambda obj: obj.power_port_count, permission='dcim.view_powerport', weight=570, hide_if_empty=True ) @register_model_view(Device, 'poweroutlets', path='power-outlets') class DevicePowerOutletsView(DeviceComponentsView): child_model = PowerOutlet table = tables.DevicePowerOutletTable filterset = filtersets.PowerOutletFilterSet template_name = 'dcim/device/poweroutlets.html' tab = ViewTab( label=_('Power Outlets'), badge=lambda obj: obj.power_outlet_count, permission='dcim.view_poweroutlet', weight=580, hide_if_empty=True ) @register_model_view(Device, 'interfaces') class DeviceInterfacesView(DeviceComponentsView): child_model = Interface table = tables.DeviceInterfaceTable filterset = filtersets.InterfaceFilterSet template_name = 'dcim/device/interfaces.html' tab = ViewTab( label=_('Interfaces'), badge=lambda obj: obj.vc_interfaces().count(), permission='dcim.view_interface', weight=520, hide_if_empty=True ) def get_children(self, request, parent): return parent.vc_interfaces().restrict(request.user, 'view').prefetch_related( Prefetch('ip_addresses', queryset=IPAddress.objects.restrict(request.user)), Prefetch('member_interfaces', queryset=Interface.objects.restrict(request.user)) ) @register_model_view(Device, 'frontports', path='front-ports') class DeviceFrontPortsView(DeviceComponentsView): child_model = FrontPort table = tables.DeviceFrontPortTable filterset = filtersets.FrontPortFilterSet template_name = 'dcim/device/frontports.html' tab = ViewTab( label=_('Front Ports'), badge=lambda obj: obj.front_port_count, permission='dcim.view_frontport', weight=530, hide_if_empty=True ) @register_model_view(Device, 'rearports', path='rear-ports') class DeviceRearPortsView(DeviceComponentsView): child_model = RearPort table = tables.DeviceRearPortTable filterset = filtersets.RearPortFilterSet template_name = 'dcim/device/rearports.html' tab = ViewTab( label=_('Rear Ports'), badge=lambda obj: obj.rear_port_count, permission='dcim.view_rearport', weight=540, hide_if_empty=True ) @register_model_view(Device, 'modulebays', path='module-bays') class DeviceModuleBaysView(DeviceComponentsView): child_model = ModuleBay table = tables.DeviceModuleBayTable filterset = filtersets.ModuleBayFilterSet template_name = 'dcim/device/modulebays.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } tab = ViewTab( label=_('Module Bays'), badge=lambda obj: obj.module_bay_count, permission='dcim.view_modulebay', weight=510, hide_if_empty=True ) @register_model_view(Device, 'devicebays', path='device-bays') class DeviceDeviceBaysView(DeviceComponentsView): child_model = DeviceBay table = tables.DeviceDeviceBayTable filterset = filtersets.DeviceBayFilterSet template_name = 'dcim/device/devicebays.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } tab = ViewTab( label=_('Device Bays'), badge=lambda obj: obj.device_bay_count, permission='dcim.view_devicebay', weight=500, hide_if_empty=True ) @register_model_view(Device, 'inventory') class DeviceInventoryView(DeviceComponentsView): child_model = InventoryItem table = tables.DeviceInventoryItemTable filterset = filtersets.InventoryItemFilterSet template_name = 'dcim/device/inventory.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } tab = ViewTab( label=_('Inventory Items'), badge=lambda obj: obj.inventory_item_count, permission='dcim.view_inventoryitem', weight=590, hide_if_empty=True ) @register_model_view(Device, 'configcontext', path='config-context') class DeviceConfigContextView(ObjectConfigContextView): queryset = Device.objects.annotate_config_context_data() base_template = 'dcim/device/base.html' tab = ViewTab( label=_('Config Context'), weight=2000 ) @register_model_view(Device, 'render-config') class DeviceRenderConfigView(generic.ObjectView): queryset = Device.objects.all() template_name = 'dcim/device/render_config.html' tab = ViewTab( label=_('Render Config'), weight=2100 ) def get(self, request, **kwargs): instance = self.get_object(**kwargs) context = self.get_extra_context(request, instance) # If a direct export has been requested, return the rendered template content as a # downloadable file. if request.GET.get('export'): response = HttpResponse(context['rendered_config'], content_type='text') filename = f"{instance.name or 'config'}.txt" response['Content-Disposition'] = f'attachment; filename="{filename}"' return response return render(request, self.get_template_name(), { 'object': instance, 'tab': self.tab, **context, }) def get_extra_context(self, request, instance): # Compile context data context_data = instance.get_config_context() context_data.update({'device': instance}) # Render the config template rendered_config = None if config_template := instance.get_config_template(): try: rendered_config = config_template.render(context=context_data) except TemplateError as e: messages.error(request, f"An error occurred while rendering the template: {e}") rendered_config = traceback.format_exc() return { 'config_template': config_template, 'context_data': context_data, 'rendered_config': rendered_config, } class DeviceBulkImportView(generic.BulkImportView): queryset = Device.objects.all() model_form = forms.DeviceImportForm def save_object(self, object_form, request): obj = object_form.save() # For child devices, save the reverse relation to the parent device bay if getattr(obj, 'parent_bay', None): device_bay = obj.parent_bay device_bay.installed_device = obj device_bay.save() return obj class DeviceBulkEditView(generic.BulkEditView): queryset = Device.objects.prefetch_related('device_type__manufacturer') filterset = filtersets.DeviceFilterSet table = tables.DeviceTable form = forms.DeviceBulkEditForm class DeviceBulkDeleteView(generic.BulkDeleteView): queryset = Device.objects.prefetch_related('device_type__manufacturer') filterset = filtersets.DeviceFilterSet table = tables.DeviceTable class DeviceBulkRenameView(generic.BulkRenameView): queryset = Device.objects.all() filterset = filtersets.DeviceFilterSet table = tables.DeviceTable @register_model_view(Device, 'contacts') class DeviceContactsView(ObjectContactsView): queryset = Device.objects.all() # # Modules # class ModuleListView(generic.ObjectListView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet filterset_form = forms.ModuleFilterForm table = tables.ModuleTable @register_model_view(Module) class ModuleView(generic.ObjectView): queryset = Module.objects.all() def get_extra_context(self, request, instance): related_models = ( (Interface.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (ConsolePort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (ConsoleServerPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (PowerPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (PowerOutlet.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (FrontPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), (RearPort.objects.restrict(request.user, 'view').filter(module=instance), 'module_id'), ) return { 'related_models': related_models, } @register_model_view(Module, 'edit') class ModuleEditView(generic.ObjectEditView): queryset = Module.objects.all() form = forms.ModuleForm @register_model_view(Module, 'delete') class ModuleDeleteView(generic.ObjectDeleteView): queryset = Module.objects.all() class ModuleBulkImportView(generic.BulkImportView): queryset = Module.objects.all() model_form = forms.ModuleImportForm class ModuleBulkEditView(generic.BulkEditView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet table = tables.ModuleTable form = forms.ModuleBulkEditForm class ModuleBulkDeleteView(generic.BulkDeleteView): queryset = Module.objects.prefetch_related('module_type__manufacturer') filterset = filtersets.ModuleFilterSet table = tables.ModuleTable # # Console ports # class ConsolePortListView(generic.ObjectListView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet filterset_form = forms.ConsolePortFilterForm table = tables.ConsolePortTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(ConsolePort) class ConsolePortView(generic.ObjectView): queryset = ConsolePort.objects.all() class ConsolePortCreateView(generic.ComponentCreateView): queryset = ConsolePort.objects.all() form = forms.ConsolePortCreateForm model_form = forms.ConsolePortForm @register_model_view(ConsolePort, 'edit') class ConsolePortEditView(generic.ObjectEditView): queryset = ConsolePort.objects.all() form = forms.ConsolePortForm @register_model_view(ConsolePort, 'delete') class ConsolePortDeleteView(generic.ObjectDeleteView): queryset = ConsolePort.objects.all() class ConsolePortBulkImportView(generic.BulkImportView): queryset = ConsolePort.objects.all() model_form = forms.ConsolePortImportForm class ConsolePortBulkEditView(generic.BulkEditView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet table = tables.ConsolePortTable form = forms.ConsolePortBulkEditForm class ConsolePortBulkRenameView(generic.BulkRenameView): queryset = ConsolePort.objects.all() class ConsolePortBulkDisconnectView(BulkDisconnectView): queryset = ConsolePort.objects.all() class ConsolePortBulkDeleteView(generic.BulkDeleteView): queryset = ConsolePort.objects.all() filterset = filtersets.ConsolePortFilterSet table = tables.ConsolePortTable # Trace view register_model_view(ConsolePort, 'trace', kwargs={'model': ConsolePort})(PathTraceView) # # Console server ports # class ConsoleServerPortListView(generic.ObjectListView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet filterset_form = forms.ConsoleServerPortFilterForm table = tables.ConsoleServerPortTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(ConsoleServerPort) class ConsoleServerPortView(generic.ObjectView): queryset = ConsoleServerPort.objects.all() class ConsoleServerPortCreateView(generic.ComponentCreateView): queryset = ConsoleServerPort.objects.all() form = forms.ConsoleServerPortCreateForm model_form = forms.ConsoleServerPortForm @register_model_view(ConsoleServerPort, 'edit') class ConsoleServerPortEditView(generic.ObjectEditView): queryset = ConsoleServerPort.objects.all() form = forms.ConsoleServerPortForm @register_model_view(ConsoleServerPort, 'delete') class ConsoleServerPortDeleteView(generic.ObjectDeleteView): queryset = ConsoleServerPort.objects.all() class ConsoleServerPortBulkImportView(generic.BulkImportView): queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortImportForm class ConsoleServerPortBulkEditView(generic.BulkEditView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet table = tables.ConsoleServerPortTable form = forms.ConsoleServerPortBulkEditForm class ConsoleServerPortBulkRenameView(generic.BulkRenameView): queryset = ConsoleServerPort.objects.all() class ConsoleServerPortBulkDisconnectView(BulkDisconnectView): queryset = ConsoleServerPort.objects.all() class ConsoleServerPortBulkDeleteView(generic.BulkDeleteView): queryset = ConsoleServerPort.objects.all() filterset = filtersets.ConsoleServerPortFilterSet table = tables.ConsoleServerPortTable # Trace view register_model_view(ConsoleServerPort, 'trace', kwargs={'model': ConsoleServerPort})(PathTraceView) # # Power ports # class PowerPortListView(generic.ObjectListView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet filterset_form = forms.PowerPortFilterForm table = tables.PowerPortTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(PowerPort) class PowerPortView(generic.ObjectView): queryset = PowerPort.objects.all() class PowerPortCreateView(generic.ComponentCreateView): queryset = PowerPort.objects.all() form = forms.PowerPortCreateForm model_form = forms.PowerPortForm @register_model_view(PowerPort, 'edit') class PowerPortEditView(generic.ObjectEditView): queryset = PowerPort.objects.all() form = forms.PowerPortForm @register_model_view(PowerPort, 'delete') class PowerPortDeleteView(generic.ObjectDeleteView): queryset = PowerPort.objects.all() class PowerPortBulkImportView(generic.BulkImportView): queryset = PowerPort.objects.all() model_form = forms.PowerPortImportForm class PowerPortBulkEditView(generic.BulkEditView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet table = tables.PowerPortTable form = forms.PowerPortBulkEditForm class PowerPortBulkRenameView(generic.BulkRenameView): queryset = PowerPort.objects.all() class PowerPortBulkDisconnectView(BulkDisconnectView): queryset = PowerPort.objects.all() class PowerPortBulkDeleteView(generic.BulkDeleteView): queryset = PowerPort.objects.all() filterset = filtersets.PowerPortFilterSet table = tables.PowerPortTable # Trace view register_model_view(PowerPort, 'trace', kwargs={'model': PowerPort})(PathTraceView) # # Power outlets # class PowerOutletListView(generic.ObjectListView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet filterset_form = forms.PowerOutletFilterForm table = tables.PowerOutletTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(PowerOutlet) class PowerOutletView(generic.ObjectView): queryset = PowerOutlet.objects.all() class PowerOutletCreateView(generic.ComponentCreateView): queryset = PowerOutlet.objects.all() form = forms.PowerOutletCreateForm model_form = forms.PowerOutletForm @register_model_view(PowerOutlet, 'edit') class PowerOutletEditView(generic.ObjectEditView): queryset = PowerOutlet.objects.all() form = forms.PowerOutletForm @register_model_view(PowerOutlet, 'delete') class PowerOutletDeleteView(generic.ObjectDeleteView): queryset = PowerOutlet.objects.all() class PowerOutletBulkImportView(generic.BulkImportView): queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletImportForm class PowerOutletBulkEditView(generic.BulkEditView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet table = tables.PowerOutletTable form = forms.PowerOutletBulkEditForm class PowerOutletBulkRenameView(generic.BulkRenameView): queryset = PowerOutlet.objects.all() class PowerOutletBulkDisconnectView(BulkDisconnectView): queryset = PowerOutlet.objects.all() class PowerOutletBulkDeleteView(generic.BulkDeleteView): queryset = PowerOutlet.objects.all() filterset = filtersets.PowerOutletFilterSet table = tables.PowerOutletTable # Trace view register_model_view(PowerOutlet, 'trace', kwargs={'model': PowerOutlet})(PathTraceView) # # Interfaces # class InterfaceListView(generic.ObjectListView): queryset = Interface.objects.all() filterset = filtersets.InterfaceFilterSet filterset_form = forms.InterfaceFilterForm table = tables.InterfaceTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(Interface) class InterfaceView(generic.ObjectView): queryset = Interface.objects.all() def get_extra_context(self, request, instance): # Get assigned VDCs vdc_table = tables.VirtualDeviceContextTable( data=instance.vdcs.restrict(request.user, 'view').prefetch_related('device'), exclude=( 'tenant', 'tenant_group', 'primary_ip', 'primary_ip4', 'primary_ip6', 'oob_ip', 'comments', 'tags', 'created', 'last_updated', 'actions', ), orderable=False ) # Get bridge interfaces bridge_interfaces = Interface.objects.restrict(request.user, 'view').filter(bridge=instance) bridge_interfaces_tables = tables.InterfaceTable( bridge_interfaces, exclude=('device', 'parent'), orderable=False ) # Get child interfaces child_interfaces = Interface.objects.restrict(request.user, 'view').filter(parent=instance) child_interfaces_tables = tables.InterfaceTable( child_interfaces, exclude=('device', 'parent'), orderable=False ) # Get assigned VLANs and annotate whether each is tagged or untagged vlans = [] if instance.untagged_vlan is not None: vlans.append(instance.untagged_vlan) vlans[0].tagged = False for vlan in instance.tagged_vlans.restrict(request.user).prefetch_related('site', 'group', 'tenant', 'role'): vlan.tagged = True vlans.append(vlan) vlan_table = InterfaceVLANTable( interface=instance, data=vlans, orderable=False ) return { 'vdc_table': vdc_table, 'bridge_interfaces_table': bridge_interfaces_tables, 'child_interfaces_table': child_interfaces_tables, 'vlan_table': vlan_table, } class InterfaceCreateView(generic.ComponentCreateView): queryset = Interface.objects.all() form = forms.InterfaceCreateForm model_form = forms.InterfaceForm @register_model_view(Interface, 'edit') class InterfaceEditView(generic.ObjectEditView): queryset = Interface.objects.all() form = forms.InterfaceForm @register_model_view(Interface, 'delete') class InterfaceDeleteView(generic.ObjectDeleteView): queryset = Interface.objects.all() class InterfaceBulkImportView(generic.BulkImportView): queryset = Interface.objects.all() model_form = forms.InterfaceImportForm class InterfaceBulkEditView(generic.BulkEditView): queryset = Interface.objects.all() filterset = filtersets.InterfaceFilterSet table = tables.InterfaceTable form = forms.InterfaceBulkEditForm class InterfaceBulkRenameView(generic.BulkRenameView): queryset = Interface.objects.all() class InterfaceBulkDisconnectView(BulkDisconnectView): queryset = Interface.objects.all() class InterfaceBulkDeleteView(generic.BulkDeleteView): # Ensure child interfaces are deleted prior to their parents queryset = Interface.objects.order_by('device', 'parent', CollateAsChar('_name')) filterset = filtersets.InterfaceFilterSet table = tables.InterfaceTable # Trace view register_model_view(Interface, 'trace', kwargs={'model': Interface})(PathTraceView) # # Front ports # class FrontPortListView(generic.ObjectListView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet filterset_form = forms.FrontPortFilterForm table = tables.FrontPortTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(FrontPort) class FrontPortView(generic.ObjectView): queryset = FrontPort.objects.all() class FrontPortCreateView(generic.ComponentCreateView): queryset = FrontPort.objects.all() form = forms.FrontPortCreateForm model_form = forms.FrontPortForm @register_model_view(FrontPort, 'edit') class FrontPortEditView(generic.ObjectEditView): queryset = FrontPort.objects.all() form = forms.FrontPortForm @register_model_view(FrontPort, 'delete') class FrontPortDeleteView(generic.ObjectDeleteView): queryset = FrontPort.objects.all() class FrontPortBulkImportView(generic.BulkImportView): queryset = FrontPort.objects.all() model_form = forms.FrontPortImportForm class FrontPortBulkEditView(generic.BulkEditView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet table = tables.FrontPortTable form = forms.FrontPortBulkEditForm class FrontPortBulkRenameView(generic.BulkRenameView): queryset = FrontPort.objects.all() class FrontPortBulkDisconnectView(BulkDisconnectView): queryset = FrontPort.objects.all() class FrontPortBulkDeleteView(generic.BulkDeleteView): queryset = FrontPort.objects.all() filterset = filtersets.FrontPortFilterSet table = tables.FrontPortTable # Trace view register_model_view(FrontPort, 'trace', kwargs={'model': FrontPort})(PathTraceView) # # Rear ports # class RearPortListView(generic.ObjectListView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet filterset_form = forms.RearPortFilterForm table = tables.RearPortTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(RearPort) class RearPortView(generic.ObjectView): queryset = RearPort.objects.all() class RearPortCreateView(generic.ComponentCreateView): queryset = RearPort.objects.all() form = forms.RearPortCreateForm model_form = forms.RearPortForm @register_model_view(RearPort, 'edit') class RearPortEditView(generic.ObjectEditView): queryset = RearPort.objects.all() form = forms.RearPortForm @register_model_view(RearPort, 'delete') class RearPortDeleteView(generic.ObjectDeleteView): queryset = RearPort.objects.all() class RearPortBulkImportView(generic.BulkImportView): queryset = RearPort.objects.all() model_form = forms.RearPortImportForm class RearPortBulkEditView(generic.BulkEditView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet table = tables.RearPortTable form = forms.RearPortBulkEditForm class RearPortBulkRenameView(generic.BulkRenameView): queryset = RearPort.objects.all() class RearPortBulkDisconnectView(BulkDisconnectView): queryset = RearPort.objects.all() class RearPortBulkDeleteView(generic.BulkDeleteView): queryset = RearPort.objects.all() filterset = filtersets.RearPortFilterSet table = tables.RearPortTable # Trace view register_model_view(RearPort, 'trace', kwargs={'model': RearPort})(PathTraceView) # # Module bays # class ModuleBayListView(generic.ObjectListView): queryset = ModuleBay.objects.select_related('installed_module__module_type') filterset = filtersets.ModuleBayFilterSet filterset_form = forms.ModuleBayFilterForm table = tables.ModuleBayTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(ModuleBay) class ModuleBayView(generic.ObjectView): queryset = ModuleBay.objects.all() class ModuleBayCreateView(generic.ComponentCreateView): queryset = ModuleBay.objects.all() form = forms.ModuleBayCreateForm model_form = forms.ModuleBayForm @register_model_view(ModuleBay, 'edit') class ModuleBayEditView(generic.ObjectEditView): queryset = ModuleBay.objects.all() form = forms.ModuleBayForm @register_model_view(ModuleBay, 'delete') class ModuleBayDeleteView(generic.ObjectDeleteView): queryset = ModuleBay.objects.all() class ModuleBayBulkImportView(generic.BulkImportView): queryset = ModuleBay.objects.all() model_form = forms.ModuleBayImportForm class ModuleBayBulkEditView(generic.BulkEditView): queryset = ModuleBay.objects.all() filterset = filtersets.ModuleBayFilterSet table = tables.ModuleBayTable form = forms.ModuleBayBulkEditForm class ModuleBayBulkRenameView(generic.BulkRenameView): queryset = ModuleBay.objects.all() class ModuleBayBulkDeleteView(generic.BulkDeleteView): queryset = ModuleBay.objects.all() filterset = filtersets.ModuleBayFilterSet table = tables.ModuleBayTable # # Device bays # class DeviceBayListView(generic.ObjectListView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet filterset_form = forms.DeviceBayFilterForm table = tables.DeviceBayTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(DeviceBay) class DeviceBayView(generic.ObjectView): queryset = DeviceBay.objects.all() class DeviceBayCreateView(generic.ComponentCreateView): queryset = DeviceBay.objects.all() form = forms.DeviceBayCreateForm model_form = forms.DeviceBayForm @register_model_view(DeviceBay, 'edit') class DeviceBayEditView(generic.ObjectEditView): queryset = DeviceBay.objects.all() form = forms.DeviceBayForm @register_model_view(DeviceBay, 'delete') class DeviceBayDeleteView(generic.ObjectDeleteView): queryset = DeviceBay.objects.all() @register_model_view(DeviceBay, 'populate') class DeviceBayPopulateView(generic.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': self.get_return_url(request, device_bay), }) 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.snapshot() 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_url = self.get_return_url(request) return redirect(return_url) return render(request, 'dcim/devicebay_populate.html', { 'device_bay': device_bay, 'form': form, 'return_url': self.get_return_url(request, device_bay), }) @register_model_view(DeviceBay, 'depopulate') class DeviceBayDepopulateView(generic.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': self.get_return_url(request, device_bay), }) def post(self, request, pk): device_bay = get_object_or_404(self.queryset, pk=pk) form = ConfirmationForm(request.POST) if form.is_valid(): device_bay.snapshot() removed_device = device_bay.installed_device device_bay.installed_device = None device_bay.save() messages.success(request, f"{removed_device} has been removed from {device_bay}.") return_url = self.get_return_url(request, device_bay.device) return redirect(return_url) return render(request, 'dcim/devicebay_depopulate.html', { 'device_bay': device_bay, 'form': form, 'return_url': self.get_return_url(request, device_bay), }) class DeviceBayBulkImportView(generic.BulkImportView): queryset = DeviceBay.objects.all() model_form = forms.DeviceBayImportForm class DeviceBayBulkEditView(generic.BulkEditView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet table = tables.DeviceBayTable form = forms.DeviceBayBulkEditForm class DeviceBayBulkRenameView(generic.BulkRenameView): queryset = DeviceBay.objects.all() class DeviceBayBulkDeleteView(generic.BulkDeleteView): queryset = DeviceBay.objects.all() filterset = filtersets.DeviceBayFilterSet table = tables.DeviceBayTable # # Inventory items # class InventoryItemListView(generic.ObjectListView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet filterset_form = forms.InventoryItemFilterForm table = tables.InventoryItemTable template_name = 'dcim/component_list.html' actions = { **DEFAULT_ACTION_PERMISSIONS, 'bulk_rename': {'change'}, } @register_model_view(InventoryItem) class InventoryItemView(generic.ObjectView): queryset = InventoryItem.objects.all() @register_model_view(InventoryItem, 'edit') class InventoryItemEditView(generic.ObjectEditView): queryset = InventoryItem.objects.all() form = forms.InventoryItemForm class InventoryItemCreateView(generic.ComponentCreateView): queryset = InventoryItem.objects.all() form = forms.InventoryItemCreateForm model_form = forms.InventoryItemForm @register_model_view(InventoryItem, 'delete') class InventoryItemDeleteView(generic.ObjectDeleteView): queryset = InventoryItem.objects.all() class InventoryItemBulkImportView(generic.BulkImportView): queryset = InventoryItem.objects.all() model_form = forms.InventoryItemImportForm class InventoryItemBulkEditView(generic.BulkEditView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet table = tables.InventoryItemTable form = forms.InventoryItemBulkEditForm class InventoryItemBulkRenameView(generic.BulkRenameView): queryset = InventoryItem.objects.all() class InventoryItemBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItem.objects.all() filterset = filtersets.InventoryItemFilterSet table = tables.InventoryItemTable @register_model_view(InventoryItem, 'children') class InventoryItemChildrenView(generic.ObjectChildrenView): queryset = InventoryItem.objects.all() child_model = InventoryItem table = tables.InventoryItemTable filterset = filtersets.InventoryItemFilterSet template_name = 'generic/object_children.html' tab = ViewTab( label=_('Children'), badge=lambda obj: obj.child_items.count(), permission='dcim.view_inventoryitem', hide_if_empty=True, weight=5000 ) def get_children(self, request, parent): return parent.child_items.restrict(request.user, 'view') # # Inventory item roles # class InventoryItemRoleListView(generic.ObjectListView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), ) filterset = filtersets.InventoryItemRoleFilterSet filterset_form = forms.InventoryItemRoleFilterForm table = tables.InventoryItemRoleTable @register_model_view(InventoryItemRole) class InventoryItemRoleView(generic.ObjectView): queryset = InventoryItemRole.objects.all() def get_extra_context(self, request, instance): return { 'inventoryitem_count': InventoryItem.objects.filter(role=instance).count(), } @register_model_view(InventoryItemRole, 'edit') class InventoryItemRoleEditView(generic.ObjectEditView): queryset = InventoryItemRole.objects.all() form = forms.InventoryItemRoleForm @register_model_view(InventoryItemRole, 'delete') class InventoryItemRoleDeleteView(generic.ObjectDeleteView): queryset = InventoryItemRole.objects.all() class InventoryItemRoleBulkImportView(generic.BulkImportView): queryset = InventoryItemRole.objects.all() model_form = forms.InventoryItemRoleImportForm class InventoryItemRoleBulkEditView(generic.BulkEditView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), ) filterset = filtersets.InventoryItemRoleFilterSet table = tables.InventoryItemRoleTable form = forms.InventoryItemRoleBulkEditForm class InventoryItemRoleBulkDeleteView(generic.BulkDeleteView): queryset = InventoryItemRole.objects.annotate( inventoryitem_count=count_related(InventoryItem, 'role'), ) filterset = filtersets.InventoryItemRoleFilterSet table = tables.InventoryItemRoleTable # # Bulk Device component creation # class DeviceBulkAddConsolePortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.ConsolePortBulkCreateForm queryset = ConsolePort.objects.all() model_form = forms.ConsolePortForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddConsoleServerPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.ConsoleServerPortBulkCreateForm queryset = ConsoleServerPort.objects.all() model_form = forms.ConsoleServerPortForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddPowerPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.PowerPortBulkCreateForm queryset = PowerPort.objects.all() model_form = forms.PowerPortForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddPowerOutletView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.PowerOutletBulkCreateForm queryset = PowerOutlet.objects.all() model_form = forms.PowerOutletForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddInterfaceView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.InterfaceBulkCreateForm queryset = Interface.objects.all() model_form = forms.InterfaceForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' # class DeviceBulkAddFrontPortView(generic.BulkComponentCreateView): # parent_model = Device # parent_field = 'device' # form = forms.FrontPortBulkCreateForm # queryset = FrontPort.objects.all() # model_form = forms.FrontPortForm # filterset = filtersets.DeviceFilterSet # table = tables.DeviceTable # default_return_url = 'dcim:device_list' class DeviceBulkAddRearPortView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.RearPortBulkCreateForm queryset = RearPort.objects.all() model_form = forms.RearPortForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddModuleBayView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.ModuleBayBulkCreateForm queryset = ModuleBay.objects.all() model_form = forms.ModuleBayForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddDeviceBayView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.DeviceBayBulkCreateForm queryset = DeviceBay.objects.all() model_form = forms.DeviceBayForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' class DeviceBulkAddInventoryItemView(generic.BulkComponentCreateView): parent_model = Device parent_field = 'device' form = forms.InventoryItemBulkCreateForm queryset = InventoryItem.objects.all() model_form = forms.InventoryItemForm filterset = filtersets.DeviceFilterSet table = tables.DeviceTable default_return_url = 'dcim:device_list' # # Cables # class CableListView(generic.ObjectListView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', 'terminations___site', ) filterset = filtersets.CableFilterSet filterset_form = forms.CableFilterForm table = tables.CableTable actions = { 'import': {'add'}, 'export': {'view'}, 'bulk_edit': {'change'}, 'bulk_delete': {'delete'}, } @register_model_view(Cable) class CableView(generic.ObjectView): queryset = Cable.objects.all() @register_model_view(Cable, 'edit') class CableEditView(generic.ObjectEditView): queryset = Cable.objects.all() template_name = 'dcim/cable_edit.html' def dispatch(self, request, *args, **kwargs): # If creating a new Cable, initialize the form class using URL query params if 'pk' not in kwargs: self.form = forms.get_cable_form( a_type=CABLE_TERMINATION_TYPES.get(request.GET.get('a_terminations_type')), b_type=CABLE_TERMINATION_TYPES.get(request.GET.get('b_terminations_type')) ) return super().dispatch(request, *args, **kwargs) def get_object(self, **kwargs): """ Hack into get_object() to set the form class when editing an existing Cable, since ObjectEditView doesn't currently provide a hook for dynamic class resolution. """ obj = super().get_object(**kwargs) if obj.pk: # TODO: Optimize this logic termination_a = obj.terminations.filter(cable_end='A').first() a_type = termination_a.termination._meta.model if termination_a else None termination_b = obj.terminations.filter(cable_end='B').first() b_type = termination_b.termination._meta.model if termination_b else None self.form = forms.get_cable_form(a_type, b_type) return obj def get_extra_addanother_params(self, request): params = { 'a_terminations_type': request.GET.get('a_terminations_type'), 'b_terminations_type': request.GET.get('b_terminations_type') } for key in request.POST: if 'device' in key or 'power_panel' in key or 'circuit' in key: params.update({key: request.POST.get(key)}) return params @register_model_view(Cable, 'delete') class CableDeleteView(generic.ObjectDeleteView): queryset = Cable.objects.all() class CableBulkImportView(generic.BulkImportView): queryset = Cable.objects.all() model_form = forms.CableImportForm class CableBulkEditView(generic.BulkEditView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', 'terminations___site', ) filterset = filtersets.CableFilterSet table = tables.CableTable form = forms.CableBulkEditForm class CableBulkDeleteView(generic.BulkDeleteView): queryset = Cable.objects.prefetch_related( 'terminations__termination', 'terminations___device', 'terminations___rack', 'terminations___location', 'terminations___site', ) filterset = filtersets.CableFilterSet table = tables.CableTable # # Connections # class ConsoleConnectionsListView(generic.ObjectListView): queryset = ConsolePort.objects.filter(_path__is_complete=True) filterset = filtersets.ConsoleConnectionFilterSet filterset_form = forms.ConsoleConnectionFilterForm table = tables.ConsoleConnectionTable template_name = 'dcim/connections_list.html' actions = { 'export': {'view'}, } def get_extra_context(self, request): return { 'title': 'Console Connections' } class PowerConnectionsListView(generic.ObjectListView): queryset = PowerPort.objects.filter(_path__is_complete=True) filterset = filtersets.PowerConnectionFilterSet filterset_form = forms.PowerConnectionFilterForm table = tables.PowerConnectionTable template_name = 'dcim/connections_list.html' actions = { 'export': {'view'}, } def get_extra_context(self, request): return { 'title': 'Power Connections' } class InterfaceConnectionsListView(generic.ObjectListView): queryset = Interface.objects.filter(_path__is_complete=True) filterset = filtersets.InterfaceConnectionFilterSet filterset_form = forms.InterfaceConnectionFilterForm table = tables.InterfaceConnectionTable template_name = 'dcim/connections_list.html' actions = { 'export': {'view'}, } def get_extra_context(self, request): return { 'title': 'Interface Connections' } # # Virtual chassis # class VirtualChassisListView(generic.ObjectListView): queryset = VirtualChassis.objects.all() table = tables.VirtualChassisTable filterset = filtersets.VirtualChassisFilterSet filterset_form = forms.VirtualChassisFilterForm @register_model_view(VirtualChassis) class VirtualChassisView(generic.ObjectView): queryset = VirtualChassis.objects.all() def get_extra_context(self, request, instance): members = Device.objects.restrict(request.user).filter(virtual_chassis=instance) return { 'members': members, } class VirtualChassisCreateView(generic.ObjectEditView): queryset = VirtualChassis.objects.all() form = forms.VirtualChassisCreateForm template_name = 'dcim/virtualchassis_add.html' @register_model_view(VirtualChassis, 'edit') 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) 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) vc_form.fields['master'].queryset = members_queryset formset = VCMemberFormSet(queryset=members_queryset) return render(request, 'dcim/virtualchassis_edit.html', { 'object': virtual_chassis, '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) 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) vc_form.fields['master'].queryset = members_queryset formset = VCMemberFormSet(request.POST, queryset=members_queryset) if vc_form.is_valid() and formset.is_valid(): 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) devices = Device.objects.filter(pk__in=[m.pk for m in members]) for device in devices: device.vc_position = None device.save() for member in members: member.save() return redirect(virtual_chassis.get_absolute_url()) return render(request, 'dcim/virtualchassis_edit.html', { 'vc_form': vc_form, 'formset': formset, 'return_url': self.get_return_url(request, virtual_chassis), }) @register_model_view(VirtualChassis, 'delete') class VirtualChassisDeleteView(generic.ObjectDeleteView): queryset = VirtualChassis.objects.all() @register_model_view(VirtualChassis, 'add_member', path='add-member') class VirtualChassisAddMemberView(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) 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) 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) if membership_form.is_valid(): membership_form.save() msg = f'Added member {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) 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: messages.error(request, f'Unable to remove master device {device} from the virtual chassis.') return redirect(device.get_absolute_url()) if form.is_valid(): 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), }) class VirtualChassisBulkImportView(generic.BulkImportView): queryset = VirtualChassis.objects.all() model_form = forms.VirtualChassisImportForm class VirtualChassisBulkEditView(generic.BulkEditView): queryset = VirtualChassis.objects.all() filterset = filtersets.VirtualChassisFilterSet table = tables.VirtualChassisTable form = forms.VirtualChassisBulkEditForm class VirtualChassisBulkDeleteView(generic.BulkDeleteView): queryset = VirtualChassis.objects.all() filterset = filtersets.VirtualChassisFilterSet table = tables.VirtualChassisTable # # Power panels # class PowerPanelListView(generic.ObjectListView): queryset = PowerPanel.objects.annotate( powerfeed_count=count_related(PowerFeed, 'power_panel') ) filterset = filtersets.PowerPanelFilterSet filterset_form = forms.PowerPanelFilterForm table = tables.PowerPanelTable @register_model_view(PowerPanel) class PowerPanelView(generic.ObjectView): queryset = PowerPanel.objects.all() def get_extra_context(self, request, instance): related_models = ( (PowerFeed.objects.restrict(request.user).filter(power_panel=instance), 'power_panel_id'), ) return { 'related_models': related_models, } @register_model_view(PowerPanel, 'edit') class PowerPanelEditView(generic.ObjectEditView): queryset = PowerPanel.objects.all() form = forms.PowerPanelForm @register_model_view(PowerPanel, 'delete') class PowerPanelDeleteView(generic.ObjectDeleteView): queryset = PowerPanel.objects.all() class PowerPanelBulkImportView(generic.BulkImportView): queryset = PowerPanel.objects.all() model_form = forms.PowerPanelImportForm class PowerPanelBulkEditView(generic.BulkEditView): queryset = PowerPanel.objects.all() filterset = filtersets.PowerPanelFilterSet table = tables.PowerPanelTable form = forms.PowerPanelBulkEditForm class PowerPanelBulkDeleteView(generic.BulkDeleteView): queryset = PowerPanel.objects.annotate( powerfeed_count=count_related(PowerFeed, 'power_panel') ) filterset = filtersets.PowerPanelFilterSet table = tables.PowerPanelTable @register_model_view(PowerPanel, 'contacts') class PowerPanelContactsView(ObjectContactsView): queryset = PowerPanel.objects.all() # # Power feeds # class PowerFeedListView(generic.ObjectListView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet filterset_form = forms.PowerFeedFilterForm table = tables.PowerFeedTable @register_model_view(PowerFeed) class PowerFeedView(generic.ObjectView): queryset = PowerFeed.objects.all() @register_model_view(PowerFeed, 'edit') class PowerFeedEditView(generic.ObjectEditView): queryset = PowerFeed.objects.all() form = forms.PowerFeedForm @register_model_view(PowerFeed, 'delete') class PowerFeedDeleteView(generic.ObjectDeleteView): queryset = PowerFeed.objects.all() class PowerFeedBulkImportView(generic.BulkImportView): queryset = PowerFeed.objects.all() model_form = forms.PowerFeedImportForm class PowerFeedBulkEditView(generic.BulkEditView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet table = tables.PowerFeedTable form = forms.PowerFeedBulkEditForm class PowerFeedBulkDisconnectView(BulkDisconnectView): queryset = PowerFeed.objects.all() class PowerFeedBulkDeleteView(generic.BulkDeleteView): queryset = PowerFeed.objects.all() filterset = filtersets.PowerFeedFilterSet table = tables.PowerFeedTable # Trace view register_model_view(PowerFeed, 'trace', kwargs={'model': PowerFeed})(PathTraceView) # VDC class VirtualDeviceContextListView(generic.ObjectListView): queryset = VirtualDeviceContext.objects.annotate( interface_count=count_related(Interface, 'vdcs'), ) filterset = filtersets.VirtualDeviceContextFilterSet filterset_form = forms.VirtualDeviceContextFilterForm table = tables.VirtualDeviceContextTable @register_model_view(VirtualDeviceContext) class VirtualDeviceContextView(generic.ObjectView): queryset = VirtualDeviceContext.objects.all() def get_extra_context(self, request, instance): related_models = ( (Interface.objects.restrict(request.user, 'view').filter(vdcs__in=[instance]), 'vdc_id'), ) return { 'related_models': related_models, } @register_model_view(VirtualDeviceContext, 'edit') class VirtualDeviceContextEditView(generic.ObjectEditView): queryset = VirtualDeviceContext.objects.all() form = forms.VirtualDeviceContextForm @register_model_view(VirtualDeviceContext, 'delete') class VirtualDeviceContextDeleteView(generic.ObjectDeleteView): queryset = VirtualDeviceContext.objects.all() class VirtualDeviceContextBulkImportView(generic.BulkImportView): queryset = VirtualDeviceContext.objects.all() model_form = forms.VirtualDeviceContextImportForm class VirtualDeviceContextBulkEditView(generic.BulkEditView): queryset = VirtualDeviceContext.objects.all() filterset = filtersets.VirtualDeviceContextFilterSet table = tables.VirtualDeviceContextTable form = forms.VirtualDeviceContextBulkEditForm class VirtualDeviceContextBulkDeleteView(generic.BulkDeleteView): queryset = VirtualDeviceContext.objects.all() filterset = filtersets.VirtualDeviceContextFilterSet table = tables.VirtualDeviceContextTable