Code cleanup

This commit is contained in:
Jeremy Stretch 2016-05-18 16:02:53 -04:00
parent 4de5f992be
commit 112e2ccde7
12 changed files with 270 additions and 223 deletions

View File

@ -1,7 +1,7 @@
import django_filters import django_filters
from dcim.models import Site from dcim.models import Site
from circuits.models import Provider, Circuit, CircuitType from .models import Provider, Circuit, CircuitType
class CircuitFilter(django_filters.FilterSet): class CircuitFilter(django_filters.FilterSet):

View File

@ -4,7 +4,7 @@ from django.db.models import Count
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from utilities.views import ( from utilities.views import (
BulkImportView, BulkEditView, BulkDeleteView, ObjectListView, ObjectEditView, ObjectDeleteView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
) )
from . import forms from . import forms

View File

@ -1,7 +1,11 @@
from django.contrib import admin from django.contrib import admin
from django.db.models import Count from django.db.models import Count
from .models import * from .models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType,
Interface, InterfaceTemplate, Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort,
PowerPortTemplate, Rack, RackGroup, Site,
)
@admin.register(Site) @admin.register(Site)
@ -143,6 +147,7 @@ class InterfaceAdmin(admin.TabularInline):
class ModuleAdmin(admin.TabularInline): class ModuleAdmin(admin.TabularInline):
model = Module model = Module
@admin.register(Device) @admin.register(Device)
class DeviceAdmin(admin.ModelAdmin): class DeviceAdmin(admin.ModelAdmin):
inlines = [ inlines = [

View File

@ -1,9 +1,11 @@
from rest_framework import serializers from rest_framework import serializers
from ipam.models import IPAddress from ipam.models import IPAddress
from dcim.models import Site, Rack, RackGroup, Manufacturer, ConsolePortTemplate, ConsoleServerPortTemplate, \ from dcim.models import (
PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate, DeviceType, DeviceRole, Platform, Device, ConsolePort, \ ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceType, DeviceRole,
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, RACK_FACE_FRONT, RACK_FACE_REAR Interface, InterfaceConnection, InterfaceTemplate, Manufacturer, Platform, PowerOutlet, PowerOutletTemplate,
PowerPort, PowerPortTemplate, Rack, RackGroup, RACK_FACE_FRONT, RACK_FACE_REAR, Site,
)
# #

View File

@ -44,7 +44,8 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/$', DeviceDetailView.as_view(), name='device_detail'), url(r'^devices/(?P<pk>\d+)/$', DeviceDetailView.as_view(), name='device_detail'),
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', LLDPNeighborsView.as_view(), name='device_lldp-neighbors'), url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', LLDPNeighborsView.as_view(), name='device_lldp-neighbors'),
url(r'^devices/(?P<pk>\d+)/console-ports/$', ConsolePortListView.as_view(), name='device_consoleports'), url(r'^devices/(?P<pk>\d+)/console-ports/$', ConsolePortListView.as_view(), name='device_consoleports'),
url(r'^devices/(?P<pk>\d+)/console-server-ports/$', ConsoleServerPortListView.as_view(), name='device_consoleserverports'), url(r'^devices/(?P<pk>\d+)/console-server-ports/$', ConsoleServerPortListView.as_view(),
name='device_consoleserverports'),
url(r'^devices/(?P<pk>\d+)/power-ports/$', PowerPortListView.as_view(), name='device_powerports'), url(r'^devices/(?P<pk>\d+)/power-ports/$', PowerPortListView.as_view(), name='device_powerports'),
url(r'^devices/(?P<pk>\d+)/power-outlets/$', PowerOutletListView.as_view(), name='device_poweroutlets'), url(r'^devices/(?P<pk>\d+)/power-outlets/$', PowerOutletListView.as_view(), name='device_poweroutlets'),
url(r'^devices/(?P<pk>\d+)/interfaces/$', InterfaceListView.as_view(), name='device_interfaces'), url(r'^devices/(?P<pk>\d+)/interfaces/$', InterfaceListView.as_view(), name='device_interfaces'),
@ -57,7 +58,8 @@ urlpatterns = [
# Interfaces # Interfaces
url(r'^interfaces/(?P<pk>\d+)/$', InterfaceDetailView.as_view(), name='interface_detail'), url(r'^interfaces/(?P<pk>\d+)/$', InterfaceDetailView.as_view(), name='interface_detail'),
url(r'^interfaces/(?P<pk>\d+)/graphs/$', GraphListView.as_view(), {'type': GRAPH_TYPE_INTERFACE}, name='interface_graphs'), url(r'^interfaces/(?P<pk>\d+)/graphs/$', GraphListView.as_view(), {'type': GRAPH_TYPE_INTERFACE},
name='interface_graphs'),
url(r'^interface-connections/(?P<pk>\d+)/$', InterfaceConnectionView.as_view(), name='interfaceconnection'), url(r'^interface-connections/(?P<pk>\d+)/$', InterfaceConnectionView.as_view(), name='interfaceconnection'),
# Miscellaneous # Miscellaneous

View File

@ -8,14 +8,13 @@ from django.conf import settings
from django.http import Http404 from django.http import Http404
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from dcim.models import Site, Rack, RackGroup, Manufacturer, DeviceType, DeviceRole, Platform, Device, ConsolePort, \ from dcim.models import (
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, IFACE_FF_VIRTUAL ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, IFACE_FF_VIRTUAL, Interface, InterfaceConnection,
from dcim.filters import RackGroupFilter, RackFilter, DeviceTypeFilter, DeviceFilter, InterfaceFilter Manufacturer, Platform, PowerOutlet, PowerPort, Rack, RackGroup, Site,
)
from dcim import filters
from .exceptions import MissingFilterException from .exceptions import MissingFilterException
from .serializers import SiteSerializer, RackGroupSerializer, RackSerializer, RackDetailSerializer, \ from . import serializers
ManufacturerSerializer, DeviceTypeSerializer, DeviceRoleSerializer, PlatformSerializer, DeviceSerializer, \
DeviceNestedSerializer, ConsolePortSerializer, ConsoleServerPortSerializer, PowerPortSerializer, \
PowerOutletSerializer, InterfaceSerializer, InterfaceDetailSerializer, InterfaceConnectionSerializer
from extras.api.renderers import BINDZoneRenderer, FlatJSONRenderer from extras.api.renderers import BINDZoneRenderer, FlatJSONRenderer
from utilities.api import ServiceUnavailable from utilities.api import ServiceUnavailable
@ -29,7 +28,7 @@ class SiteListView(generics.ListAPIView):
List all sites List all sites
""" """
queryset = Site.objects.all() queryset = Site.objects.all()
serializer_class = SiteSerializer serializer_class = serializers.SiteSerializer
class SiteDetailView(generics.RetrieveAPIView): class SiteDetailView(generics.RetrieveAPIView):
@ -37,7 +36,7 @@ class SiteDetailView(generics.RetrieveAPIView):
Retrieve a single site Retrieve a single site
""" """
queryset = Site.objects.all() queryset = Site.objects.all()
serializer_class = SiteSerializer serializer_class = serializers.SiteSerializer
# #
@ -49,8 +48,8 @@ class RackGroupListView(generics.ListAPIView):
List all rack groups List all rack groups
""" """
queryset = RackGroup.objects.all() queryset = RackGroup.objects.all()
serializer_class = RackGroupSerializer serializer_class = serializers.RackGroupSerializer
filter_class = RackGroupFilter filter_class = filters.RackGroupFilter
class RackGroupDetailView(generics.RetrieveAPIView): class RackGroupDetailView(generics.RetrieveAPIView):
@ -58,7 +57,7 @@ class RackGroupDetailView(generics.RetrieveAPIView):
Retrieve a single rack group Retrieve a single rack group
""" """
queryset = RackGroup.objects.all() queryset = RackGroup.objects.all()
serializer_class = RackGroupSerializer serializer_class = serializers.RackGroupSerializer
# #
@ -70,8 +69,8 @@ class RackListView(generics.ListAPIView):
List racks (filterable) List racks (filterable)
""" """
queryset = Rack.objects.select_related('site') queryset = Rack.objects.select_related('site')
serializer_class = RackSerializer serializer_class = serializers.RackSerializer
filter_class = RackFilter filter_class = filters.RackFilter
class RackDetailView(generics.RetrieveAPIView): class RackDetailView(generics.RetrieveAPIView):
@ -79,7 +78,7 @@ class RackDetailView(generics.RetrieveAPIView):
Retrieve a single rack Retrieve a single rack
""" """
queryset = Rack.objects.select_related('site') queryset = Rack.objects.select_related('site')
serializer_class = RackDetailSerializer serializer_class = serializers.RackDetailSerializer
# #
@ -100,7 +99,7 @@ class RackUnitListView(APIView):
# Serialize Devices within the rack elevation # Serialize Devices within the rack elevation
for u in elevation: for u in elevation:
if u['device']: if u['device']:
u['device'] = DeviceNestedSerializer(instance=u['device']).data u['device'] = serializers.DeviceNestedSerializer(instance=u['device']).data
return Response(elevation) return Response(elevation)
@ -114,7 +113,7 @@ class ManufacturerListView(generics.ListAPIView):
List all hardware manufacturers List all hardware manufacturers
""" """
queryset = Manufacturer.objects.all() queryset = Manufacturer.objects.all()
serializer_class = ManufacturerSerializer serializer_class = serializers.ManufacturerSerializer
class ManufacturerDetailView(generics.RetrieveAPIView): class ManufacturerDetailView(generics.RetrieveAPIView):
@ -122,7 +121,7 @@ class ManufacturerDetailView(generics.RetrieveAPIView):
Retrieve a single hardware manufacturers Retrieve a single hardware manufacturers
""" """
queryset = Manufacturer.objects.all() queryset = Manufacturer.objects.all()
serializer_class = ManufacturerSerializer serializer_class = serializers.ManufacturerSerializer
# #
@ -134,8 +133,8 @@ class DeviceTypeListView(generics.ListAPIView):
List device types (filterable) List device types (filterable)
""" """
queryset = DeviceType.objects.select_related('manufacturer') queryset = DeviceType.objects.select_related('manufacturer')
serializer_class = DeviceTypeSerializer serializer_class = serializers.DeviceTypeSerializer
filter_class = DeviceTypeFilter filter_class = filters.DeviceTypeFilter
class DeviceTypeDetailView(generics.RetrieveAPIView): class DeviceTypeDetailView(generics.RetrieveAPIView):
@ -143,7 +142,7 @@ class DeviceTypeDetailView(generics.RetrieveAPIView):
Retrieve a single device type Retrieve a single device type
""" """
queryset = DeviceType.objects.select_related('manufacturer') queryset = DeviceType.objects.select_related('manufacturer')
serializer_class = DeviceTypeSerializer serializer_class = serializers.DeviceTypeSerializer
# #
@ -155,7 +154,7 @@ class DeviceRoleListView(generics.ListAPIView):
List all device roles List all device roles
""" """
queryset = DeviceRole.objects.all() queryset = DeviceRole.objects.all()
serializer_class = DeviceRoleSerializer serializer_class = serializers.DeviceRoleSerializer
class DeviceRoleDetailView(generics.RetrieveAPIView): class DeviceRoleDetailView(generics.RetrieveAPIView):
@ -163,7 +162,7 @@ class DeviceRoleDetailView(generics.RetrieveAPIView):
Retrieve a single device role Retrieve a single device role
""" """
queryset = DeviceRole.objects.all() queryset = DeviceRole.objects.all()
serializer_class = DeviceRoleSerializer serializer_class = serializers.DeviceRoleSerializer
# #
@ -175,7 +174,7 @@ class PlatformListView(generics.ListAPIView):
List all platforms List all platforms
""" """
queryset = Platform.objects.all() queryset = Platform.objects.all()
serializer_class = PlatformSerializer serializer_class = serializers.PlatformSerializer
class PlatformDetailView(generics.RetrieveAPIView): class PlatformDetailView(generics.RetrieveAPIView):
@ -183,7 +182,7 @@ class PlatformDetailView(generics.RetrieveAPIView):
Retrieve a single platform Retrieve a single platform
""" """
queryset = Platform.objects.all() queryset = Platform.objects.all()
serializer_class = PlatformSerializer serializer_class = serializers.PlatformSerializer
# #
@ -196,8 +195,8 @@ class DeviceListView(generics.ListAPIView):
""" """
queryset = Device.objects.select_related('device_type__manufacturer', 'device_role', 'platform', 'rack__site')\ queryset = Device.objects.select_related('device_type__manufacturer', 'device_role', 'platform', 'rack__site')\
.prefetch_related('primary_ip__nat_outside') .prefetch_related('primary_ip__nat_outside')
serializer_class = DeviceSerializer serializer_class = serializers.DeviceSerializer
filter_class = DeviceFilter filter_class = filters.DeviceFilter
renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer, FlatJSONRenderer] renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer, FlatJSONRenderer]
@ -206,7 +205,7 @@ class DeviceDetailView(generics.RetrieveAPIView):
Retrieve a single device Retrieve a single device
""" """
queryset = Device.objects.all() queryset = Device.objects.all()
serializer_class = DeviceSerializer serializer_class = serializers.DeviceSerializer
# #
@ -217,7 +216,7 @@ class ConsolePortListView(generics.ListAPIView):
""" """
List console ports (by device) List console ports (by device)
""" """
serializer_class = ConsolePortSerializer serializer_class = serializers.ConsolePortSerializer
def get_queryset(self): def get_queryset(self):
@ -227,7 +226,7 @@ class ConsolePortListView(generics.ListAPIView):
class ConsolePortView(generics.RetrieveUpdateDestroyAPIView): class ConsolePortView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly] permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = ConsolePortSerializer serializer_class = serializers.ConsolePortSerializer
queryset = ConsolePort.objects.all() queryset = ConsolePort.objects.all()
@ -239,7 +238,7 @@ class ConsoleServerPortListView(generics.ListAPIView):
""" """
List console server ports (by device) List console server ports (by device)
""" """
serializer_class = ConsoleServerPortSerializer serializer_class = serializers.ConsoleServerPortSerializer
def get_queryset(self): def get_queryset(self):
@ -255,7 +254,7 @@ class PowerPortListView(generics.ListAPIView):
""" """
List power ports (by device) List power ports (by device)
""" """
serializer_class = PowerPortSerializer serializer_class = serializers.PowerPortSerializer
def get_queryset(self): def get_queryset(self):
@ -265,7 +264,7 @@ class PowerPortListView(generics.ListAPIView):
class PowerPortView(generics.RetrieveUpdateDestroyAPIView): class PowerPortView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly] permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = PowerPortSerializer serializer_class = serializers.PowerPortSerializer
queryset = PowerPort.objects.all() queryset = PowerPort.objects.all()
@ -277,7 +276,7 @@ class PowerOutletListView(generics.ListAPIView):
""" """
List power outlets (by device) List power outlets (by device)
""" """
serializer_class = PowerOutletSerializer serializer_class = serializers.PowerOutletSerializer
def get_queryset(self): def get_queryset(self):
@ -293,8 +292,8 @@ class InterfaceListView(generics.ListAPIView):
""" """
List interfaces (by device) List interfaces (by device)
""" """
serializer_class = InterfaceSerializer serializer_class = serializers.InterfaceSerializer
filter_class = InterfaceFilter filter_class = filters.InterfaceFilter
def get_queryset(self): def get_queryset(self):
@ -318,12 +317,12 @@ class InterfaceDetailView(generics.RetrieveAPIView):
Retrieve a single interface Retrieve a single interface
""" """
queryset = Interface.objects.select_related('device') queryset = Interface.objects.select_related('device')
serializer_class = InterfaceDetailSerializer serializer_class = serializers.InterfaceDetailSerializer
class InterfaceConnectionView(generics.RetrieveUpdateDestroyAPIView): class InterfaceConnectionView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [DjangoModelPermissionsOrAnonReadOnly] permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
serializer_class = InterfaceConnectionSerializer serializer_class = serializers.InterfaceConnectionSerializer
queryset = InterfaceConnection.objects.all() queryset = InterfaceConnection.objects.all()
@ -341,7 +340,6 @@ class LLDPNeighborsView(APIView):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if not device.primary_ip: if not device.primary_ip:
raise ServiceUnavailable(detail="No IP configured for this device.") raise ServiceUnavailable(detail="No IP configured for this device.")
hostname = str(device.primary_ip.address.ip)
RPC = device.get_rpc_client() RPC = device.get_rpc_client()
if not RPC: if not RPC:
@ -390,7 +388,7 @@ class RelatedConnectionsView(APIView):
# Initialize response skeleton # Initialize response skeleton
response = dict() response = dict()
response['device'] = DeviceSerializer(device).data response['device'] = serializers.DeviceSerializer(device).data
response['console-ports'] = [] response['console-ports'] = []
response['power-ports'] = [] response['power-ports'] = []
response['interfaces'] = [] response['interfaces'] = []

View File

@ -2,8 +2,10 @@ import django_filters
from django.db.models import Q from django.db.models import Q
from .models import Site, RackGroup, Rack, Manufacturer, DeviceType, DeviceRole, Device, ConsolePort, \ from .models import (
ConsoleServerPort, Platform, PowerPort, PowerOutlet, Interface, InterfaceConnection ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, InterfaceConnection, Manufacturer,
Platform, PowerOutlet, PowerPort, Rack, RackGroup, Site,
)
class RackGroupFilter(django_filters.FilterSet): class RackGroupFilter(django_filters.FilterSet):

View File

@ -4,18 +4,23 @@ from django import forms
from django.db.models import Count, Q from django.db.models import Count, Q
from ipam.models import IPAddress from ipam.models import IPAddress
from utilities.forms import BootstrapMixin, SmallTextarea, SelectWithDisabled, ConfirmationForm, APISelect, \ from utilities.forms import (
Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField APISelect, BootstrapMixin, BulkImportForm, CommentField, ConfirmationForm, CSVDataField, ExpandableNameField,
FlexibleModelChoiceField, Livesearch, SelectWithDisabled, SmallTextarea,
)
from .models import Site, Rack, RackGroup, Device, Manufacturer, DeviceType, DeviceRole, Platform, ConsolePort, \ from .models import (
ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, PowerPort, PowerPortTemplate, PowerOutlet, \ CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate,
PowerOutletTemplate, Interface, InterfaceTemplate, InterfaceConnection, CONNECTION_STATUS_CHOICES, \ ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType, Interface, IFACE_FF_VIRTUAL,
CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, IFACE_FF_VIRTUAL, STATUS_CHOICES InterfaceConnection, InterfaceTemplate, Manufacturer, Platform, PowerOutlet, PowerOutletTemplate, PowerPort,
PowerPortTemplate, Rack, RackGroup, Site, STATUS_CHOICES
)
FORM_STATUS_CHOICES = [ FORM_STATUS_CHOICES = [
['', '---------'], ['', '---------'],
] ]
FORM_STATUS_CHOICES += STATUS_CHOICES FORM_STATUS_CHOICES += STATUS_CHOICES
DEVICE_BY_PK_RE = '{\d+\}' DEVICE_BY_PK_RE = '{\d+\}'
@ -182,7 +187,7 @@ class RackFilterForm(forms.Form, BootstrapMixin):
site = forms.MultipleChoiceField(required=False, choices=rack_site_choices, site = forms.MultipleChoiceField(required=False, choices=rack_site_choices,
widget=forms.SelectMultiple(attrs={'size': 8})) widget=forms.SelectMultiple(attrs={'size': 8}))
group_id = forms.MultipleChoiceField(required=False, choices=rack_group_choices, group_id = forms.MultipleChoiceField(required=False, choices=rack_group_choices,
widget=forms.SelectMultiple(attrs={'size': 8})) widget=forms.SelectMultiple(attrs={'size': 8}))
# #

View File

@ -427,10 +427,13 @@ class Device(models.Model):
name = NullableCharField(max_length=50, blank=True, null=True, unique=True) name = NullableCharField(max_length=50, blank=True, null=True, unique=True)
serial = models.CharField(max_length=50, blank=True, verbose_name='Serial number') serial = models.CharField(max_length=50, blank=True, verbose_name='Serial number')
rack = models.ForeignKey('Rack', related_name='devices', on_delete=models.PROTECT) rack = models.ForeignKey('Rack', related_name='devices', on_delete=models.PROTECT)
position = models.PositiveSmallIntegerField(blank=True, null=True, validators=[MinValueValidator(1)], verbose_name='Position (U)', help_text='Number of the lowest U position occupied by the device') position = models.PositiveSmallIntegerField(blank=True, null=True, validators=[MinValueValidator(1)],
verbose_name='Position (U)',
help_text='Number of the lowest U position occupied by the device')
face = models.PositiveSmallIntegerField(blank=True, null=True, choices=RACK_FACE_CHOICES, verbose_name='Rack face') face = models.PositiveSmallIntegerField(blank=True, null=True, choices=RACK_FACE_CHOICES, verbose_name='Rack face')
status = models.BooleanField(choices=STATUS_CHOICES, default=STATUS_ACTIVE, verbose_name='Status') status = models.BooleanField(choices=STATUS_CHOICES, default=STATUS_ACTIVE, verbose_name='Status')
primary_ip = models.OneToOneField('ipam.IPAddress', related_name='primary_for', on_delete=models.SET_NULL, blank=True, null=True, verbose_name='Primary IP') primary_ip = models.OneToOneField('ipam.IPAddress', related_name='primary_for', on_delete=models.SET_NULL,
blank=True, null=True, verbose_name='Primary IP')
ro_snmp = models.CharField(max_length=50, blank=True, verbose_name='SNMP (RO)') ro_snmp = models.CharField(max_length=50, blank=True, verbose_name='SNMP (RO)')
comments = models.TextField(blank=True) comments = models.TextField(blank=True)
@ -480,19 +483,24 @@ class Device(models.Model):
# If this is a new Device, instantiate all of the related components per the DeviceType definition # If this is a new Device, instantiate all of the related components per the DeviceType definition
if is_new: if is_new:
ConsolePort.objects.bulk_create( ConsolePort.objects.bulk_create(
[ConsolePort(device=self, name=template.name) for template in self.device_type.console_port_templates.all()] [ConsolePort(device=self, name=template.name) for template in
self.device_type.console_port_templates.all()]
) )
ConsoleServerPort.objects.bulk_create( ConsoleServerPort.objects.bulk_create(
[ConsoleServerPort(device=self, name=template.name) for template in self.device_type.cs_port_templates.all()] [ConsoleServerPort(device=self, name=template.name) for template in
self.device_type.cs_port_templates.all()]
) )
PowerPort.objects.bulk_create( PowerPort.objects.bulk_create(
[PowerPort(device=self, name=template.name) for template in self.device_type.power_port_templates.all()] [PowerPort(device=self, name=template.name) for template in
self.device_type.power_port_templates.all()]
) )
PowerOutlet.objects.bulk_create( PowerOutlet.objects.bulk_create(
[PowerOutlet(device=self, name=template.name) for template in self.device_type.power_outlet_templates.all()] [PowerOutlet(device=self, name=template.name) for template in
self.device_type.power_outlet_templates.all()]
) )
Interface.objects.bulk_create( Interface.objects.bulk_create(
[Interface(device=self, name=template.name, form_factor=template.form_factor, mgmt_only=template.mgmt_only) for template in self.device_type.interface_templates.all()] [Interface(device=self, name=template.name, form_factor=template.form_factor,
mgmt_only=template.mgmt_only) for template in self.device_type.interface_templates.all()]
) )
def get_rpc_client(self): def get_rpc_client(self):
@ -510,7 +518,8 @@ class ConsolePort(models.Model):
""" """
device = models.ForeignKey('Device', related_name='console_ports', on_delete=models.CASCADE) device = models.ForeignKey('Device', related_name='console_ports', on_delete=models.CASCADE)
name = models.CharField(max_length=30) name = models.CharField(max_length=30)
cs_port = models.OneToOneField('ConsoleServerPort', related_name='connected_console', on_delete=models.SET_NULL, verbose_name='Console server port', blank=True, null=True) cs_port = models.OneToOneField('ConsoleServerPort', related_name='connected_console', on_delete=models.SET_NULL,
verbose_name='Console server port', blank=True, null=True)
connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED) connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED)
class Meta: class Meta:
@ -558,7 +567,8 @@ class PowerPort(models.Model):
""" """
device = models.ForeignKey('Device', related_name='power_ports', on_delete=models.CASCADE) device = models.ForeignKey('Device', related_name='power_ports', on_delete=models.CASCADE)
name = models.CharField(max_length=30) name = models.CharField(max_length=30)
power_outlet = models.OneToOneField('PowerOutlet', related_name='connected_port', on_delete=models.SET_NULL, blank=True, null=True) power_outlet = models.OneToOneField('PowerOutlet', related_name='connected_port', on_delete=models.SET_NULL,
blank=True, null=True)
connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED) connection_status = models.NullBooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED)
class Meta: class Meta:
@ -573,7 +583,8 @@ class PowerOutletManager(models.Manager):
def get_queryset(self): def get_queryset(self):
return super(PowerOutletManager, self).get_queryset().extra(select={ return super(PowerOutletManager, self).get_queryset().extra(select={
'name_padded': "CONCAT(SUBSTRING(dcim_poweroutlet.name FROM '^[^0-9]+'), LPAD(SUBSTRING(dcim_poweroutlet.name FROM '[0-9\/]+$'), 8, '0'))", 'name_padded': "CONCAT(SUBSTRING(dcim_poweroutlet.name FROM '^[^0-9]+'), "
"LPAD(SUBSTRING(dcim_poweroutlet.name FROM '[0-9\/]+$'), 8, '0'))",
}).order_by('device', 'name_padded') }).order_by('device', 'name_padded')
@ -678,7 +689,8 @@ class InterfaceConnection(models.Model):
""" """
interface_a = models.OneToOneField('Interface', related_name='connected_as_a', on_delete=models.CASCADE) interface_a = models.OneToOneField('Interface', related_name='connected_as_a', on_delete=models.CASCADE)
interface_b = models.OneToOneField('Interface', related_name='connected_as_b', on_delete=models.CASCADE) interface_b = models.OneToOneField('Interface', related_name='connected_as_b', on_delete=models.CASCADE)
connection_status = models.BooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED, verbose_name='Status') connection_status = models.BooleanField(choices=CONNECTION_STATUS_CHOICES, default=CONNECTION_STATUS_CONNECTED,
verbose_name='Status')
def clean(self): def clean(self):

View File

@ -1,31 +1,48 @@
import django_tables2 as tables import django_tables2 as tables
from django_tables2.utils import Accessor from django_tables2.utils import Accessor
from .models import Site, RackGroup, Rack, Manufacturer, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate,\ from .models import (
PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate, DeviceRole, Platform, Device, ConsolePort, PowerPort ConsolePort, ConsolePortTemplate, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType, InterfaceTemplate,
Manufacturer, Platform, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, Site,
)
DEVICE_LINK = """ DEVICE_LINK = """
<a href="{% url 'dcim:device' pk=record.pk %}">{{ record.name|default:'<span class="label label-info">Unnamed device</span>' }}</a> <a href="{% url 'dcim:device' pk=record.pk %}">
{{ record.name|default:'<span class="label label-info">Unnamed device</span>' }}
</a>
""" """
RACKGROUP_EDIT_LINK = """ RACKGROUP_EDIT_LINK = """
{% if perms.dcim.change_rackgroup %}<a href="{% url 'dcim:rackgroup_edit' pk=record.pk %}">Edit</a>{% endif %} {% if perms.dcim.change_rackgroup %}
<a href="{% url 'dcim:rackgroup_edit' pk=record.pk %}">Edit</a>
{% endif %}
""" """
DEVICEROLE_EDIT_LINK = """ DEVICEROLE_EDIT_LINK = """
{% if perms.dcim.change_devicerole %}<a href="{% url 'dcim:devicerole_edit' slug=record.slug %}">Edit</a>{% endif %} {% if perms.dcim.change_devicerole %}
<a href="{% url 'dcim:devicerole_edit' slug=record.slug %}">Edit</a>
{% endif %}
""" """
MANUFACTURER_EDIT_LINK = """ MANUFACTURER_EDIT_LINK = """
{% if perms.dcim.change_manufacturer %}<a href="{% url 'dcim:manufacturer_edit' slug=record.slug %}">Edit</a>{% endif %} {% if perms.dcim.change_manufacturer %}
<a href="{% url 'dcim:manufacturer_edit' slug=record.slug %}">Edit</a>
{% endif %}
""" """
PLATFORM_EDIT_LINK = """ PLATFORM_EDIT_LINK = """
{% if perms.dcim.change_platform %}<a href="{% url 'dcim:platform_edit' slug=record.slug %}">Edit</a>{% endif %} {% if perms.dcim.change_platform %}
<a href="{% url 'dcim:platform_edit' slug=record.slug %}">Edit</a>
{% endif %}
""" """
STATUS_ICON = """ STATUS_ICON = """
<span class="glyphicon glyphicon-{% if record.status %}ok-sign text-success" title="Active{% else %}minus-sign text-danger" title="Offline{% endif %}" aria-hidden="true"></span> {% if record.status %}
<span class="glyphicon glyphicon-ok-sign text-success" title="Active" aria-hidden="true"></span>
{% else %}
<span class="glyphicon glyphicon-minus-sign text-danger" title="Offline" aria-hidden="true"></span>
{% endif %}
""" """
@ -45,7 +62,8 @@ class SiteTable(tables.Table):
class Meta: class Meta:
model = Site model = Site
fields = ('name', 'facility', 'asn', 'rack_count', 'device_count', 'prefix_count', 'vlan_count', 'circuit_count') fields = ('name', 'facility', 'asn', 'rack_count', 'device_count', 'prefix_count', 'vlan_count',
'circuit_count')
empty_text = "No sites have been defined." empty_text = "No sites have been defined."
attrs = { attrs = {
'class': 'table table-hover', 'class': 'table table-hover',
@ -254,7 +272,8 @@ class DeviceTable(tables.Table):
rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack') rack = tables.LinkColumn('dcim:rack', args=[Accessor('rack.pk')], verbose_name='Rack')
device_role = tables.Column(verbose_name='Role') device_role = tables.Column(verbose_name='Role')
device_type = tables.Column(verbose_name='Type') device_type = tables.Column(verbose_name='Type')
primary_ip = tables.TemplateColumn(orderable=False, verbose_name='IP Address', template_code="{{ record.primary_ip.address.ip }}") primary_ip = tables.TemplateColumn(orderable=False, verbose_name='IP Address',
template_code="{{ record.primary_ip.address.ip }}")
class Meta: class Meta:
model = Device model = Device
@ -286,7 +305,8 @@ class DeviceImportTable(tables.Table):
# #
class ConsoleConnectionTable(tables.Table): class ConsoleConnectionTable(tables.Table):
console_server = tables.LinkColumn('dcim:device', accessor=Accessor('cs_port.device'), args=[Accessor('cs_port.device.pk')], verbose_name='Console server') console_server = tables.LinkColumn('dcim:device', accessor=Accessor('cs_port.device'),
args=[Accessor('cs_port.device.pk')], verbose_name='Console server')
cs_port = tables.Column(verbose_name='Port') cs_port = tables.Column(verbose_name='Port')
device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device') device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
name = tables.Column(verbose_name='Console port') name = tables.Column(verbose_name='Console port')
@ -300,7 +320,8 @@ class ConsoleConnectionTable(tables.Table):
class PowerConnectionTable(tables.Table): class PowerConnectionTable(tables.Table):
pdu = tables.LinkColumn('dcim:device', accessor=Accessor('power_outlet.device'), args=[Accessor('power_outlet.device.pk')], verbose_name='PDU') pdu = tables.LinkColumn('dcim:device', accessor=Accessor('power_outlet.device'),
args=[Accessor('power_outlet.device.pk')], verbose_name='PDU')
power_outlet = tables.Column(verbose_name='Outlet') power_outlet = tables.Column(verbose_name='Outlet')
device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device') device = tables.LinkColumn('dcim:device', args=[Accessor('device.pk')], verbose_name='Device')
name = tables.Column(verbose_name='Console port') name = tables.Column(verbose_name='Console port')
@ -314,9 +335,11 @@ class PowerConnectionTable(tables.Table):
class InterfaceConnectionTable(tables.Table): class InterfaceConnectionTable(tables.Table):
device_a = tables.LinkColumn('dcim:device', accessor=Accessor('interface_a.device'), args=[Accessor('interface_a.device.pk')], verbose_name='Device A') device_a = tables.LinkColumn('dcim:device', accessor=Accessor('interface_a.device'),
args=[Accessor('interface_a.device.pk')], verbose_name='Device A')
interface_a = tables.Column(verbose_name='Interface A') interface_a = tables.Column(verbose_name='Interface A')
device_b = tables.LinkColumn('dcim:device', accessor=Accessor('interface_b.device'), args=[Accessor('interface_b.device.pk')], verbose_name='Device B') device_b = tables.LinkColumn('dcim:device', accessor=Accessor('interface_b.device'),
args=[Accessor('interface_b.device.pk')], verbose_name='Device B')
interface_b = tables.Column(verbose_name='Interface B') interface_b = tables.Column(verbose_name='Interface B')
class Meta: class Meta:

View File

@ -3,8 +3,9 @@ from django.conf.urls import url
from secrets.views import secret_add from secrets.views import secret_add
from . import views from . import views
from .models import ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, PowerOutletTemplate, \ from .models import (
InterfaceTemplate ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate,
)
urlpatterns = [ urlpatterns = [

View File

@ -17,30 +17,16 @@ from circuits.models import Circuit
from extras.models import TopologyMap from extras.models import TopologyMap
from utilities.error_handlers import handle_protectederror from utilities.error_handlers import handle_protectederror
from utilities.forms import ConfirmationForm from utilities.forms import ConfirmationForm
from utilities.views import ObjectListView, BulkImportView, BulkEditView, BulkDeleteView, ObjectEditView,\ from utilities.views import (
ObjectDeleteView BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
from .filters import RackGroupFilter, RackFilter, DeviceTypeFilter, DeviceFilter, ConsoleConnectionFilter,\ from . import filters, forms, tables
PowerConnectionFilter, InterfaceConnectionFilter from .models import (
from .forms import SiteForm, SiteImportForm, RackGroupForm, RackGroupFilterForm, RackGroupBulkDeleteForm, RackForm,\ CONNECTION_STATUS_CONNECTED, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device,
RackImportForm, RackBulkEditForm, RackBulkDeleteForm, RackFilterForm, ManufacturerForm, ManufacturerBulkDeleteForm,\ DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate, Manufacturer, Module, Platform,
DeviceTypeForm, DeviceTypeBulkEditForm, DeviceTypeBulkDeleteForm, DeviceTypeFilterForm, DeviceRoleForm,\ PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, Site,
DeviceRoleBulkDeleteForm, PlatformForm, PlatformBulkDeleteForm, DeviceForm, DeviceImportForm, DeviceBulkEditForm,\ )
DeviceBulkDeleteForm, DeviceFilterForm, ConsolePortForm, ConsolePortCreateForm, ConsolePortConnectionForm,\
ConsoleConnectionImportForm, ConsoleServerPortForm, ConsoleServerPortCreateForm, ConsoleServerPortConnectionForm,\
PowerPortForm, PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm,\
PowerOutletCreateForm, PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm,\
InterfaceConnectionForm, InterfaceConnectionDeletionForm, InterfaceConnectionImportForm,\
ConsoleConnectionFilterForm, PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm,\
ConsolePortTemplateForm, ConsoleServerPortTemplateForm, PowerPortTemplateForm, PowerOutletTemplateForm,\
InterfaceTemplateForm
from .models import Site, RackGroup, Rack, Manufacturer, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate,\
PowerPortTemplate, PowerOutletTemplate, InterfaceTemplate, DeviceRole, Platform, Device, ConsolePort,\
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
from .tables import SiteTable, RackGroupTable, RackTable, ManufacturerTable, DeviceTypeTable, DeviceRoleTable,\
PlatformTable, DeviceTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable,\
InterfaceConnectionTable, ConsolePortTemplateTable, ConsoleServerPortTemplateTable, PowerPortTemplateTable,\
PowerOutletTemplateTable, InterfaceTemplateTable
EXPANSION_PATTERN = '\[(\d+-\d+)\]' EXPANSION_PATTERN = '\[(\d+-\d+)\]'
@ -75,7 +61,7 @@ def expand_pattern(string):
class SiteListView(ObjectListView): class SiteListView(ObjectListView):
queryset = Site.objects.all() queryset = Site.objects.all()
table = SiteTable table = tables.SiteTable
template_name = 'dcim/site_list.html' template_name = 'dcim/site_list.html'
@ -101,7 +87,7 @@ def site(request, slug):
class SiteEditView(PermissionRequiredMixin, ObjectEditView): class SiteEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_site' permission_required = 'dcim.change_site'
model = Site model = Site
form_class = SiteForm form_class = forms.SiteForm
template_name = 'dcim/site_edit.html' template_name = 'dcim/site_edit.html'
cancel_url = 'dcim:site_list' cancel_url = 'dcim:site_list'
@ -114,8 +100,8 @@ class SiteDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class SiteBulkImportView(PermissionRequiredMixin, BulkImportView): class SiteBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.add_site' permission_required = 'dcim.add_site'
form = SiteImportForm form = forms.SiteImportForm
table = SiteTable table = tables.SiteTable
template_name = 'dcim/site_import.html' template_name = 'dcim/site_import.html'
obj_list_url = 'dcim:site_list' obj_list_url = 'dcim:site_list'
@ -126,9 +112,9 @@ class SiteBulkImportView(PermissionRequiredMixin, BulkImportView):
class RackGroupListView(ObjectListView): class RackGroupListView(ObjectListView):
queryset = RackGroup.objects.annotate(rack_count=Count('racks')) queryset = RackGroup.objects.annotate(rack_count=Count('racks'))
filter = RackGroupFilter filter = filters.RackGroupFilter
filter_form = RackGroupFilterForm filter_form = forms.RackGroupFilterForm
table = RackGroupTable table = tables.RackGroupTable
edit_permissions = ['dcim.change_rackgroup', 'dcim.delete_rackgroup'] edit_permissions = ['dcim.change_rackgroup', 'dcim.delete_rackgroup']
template_name = 'dcim/rackgroup_list.html' template_name = 'dcim/rackgroup_list.html'
@ -136,14 +122,14 @@ class RackGroupListView(ObjectListView):
class RackGroupEditView(PermissionRequiredMixin, ObjectEditView): class RackGroupEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_rackgroup' permission_required = 'dcim.change_rackgroup'
model = RackGroup model = RackGroup
form_class = RackGroupForm form_class = forms.RackGroupForm
cancel_url = 'dcim:rackgroup_list' cancel_url = 'dcim:rackgroup_list'
class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_rackgroup' permission_required = 'dcim.delete_rackgroup'
cls = RackGroup cls = RackGroup
form = RackGroupBulkDeleteForm form = forms.RackGroupBulkDeleteForm
default_redirect_url = 'dcim:rackgroup_list' default_redirect_url = 'dcim:rackgroup_list'
@ -153,9 +139,9 @@ class RackGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class RackListView(ObjectListView): class RackListView(ObjectListView):
queryset = Rack.objects.select_related('site').annotate(device_count=Count('devices', distinct=True)) queryset = Rack.objects.select_related('site').annotate(device_count=Count('devices', distinct=True))
filter = RackFilter filter = filters.RackFilter
filter_form = RackFilterForm filter_form = forms.RackFilterForm
table = RackTable table = tables.RackTable
edit_permissions = ['dcim.change_rack', 'dcim.delete_rack'] edit_permissions = ['dcim.change_rack', 'dcim.delete_rack']
template_name = 'dcim/rack_list.html' template_name = 'dcim/rack_list.html'
@ -181,7 +167,7 @@ def rack(request, pk):
class RackEditView(PermissionRequiredMixin, ObjectEditView): class RackEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_rack' permission_required = 'dcim.change_rack'
model = Rack model = Rack
form_class = RackForm form_class = forms.RackForm
template_name = 'dcim/rack_edit.html' template_name = 'dcim/rack_edit.html'
cancel_url = 'dcim:rack_list' cancel_url = 'dcim:rack_list'
@ -194,8 +180,8 @@ class RackDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class RackBulkImportView(PermissionRequiredMixin, BulkImportView): class RackBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.add_rack' permission_required = 'dcim.add_rack'
form = RackImportForm form = forms.RackImportForm
table = RackTable table = tables.RackTable
template_name = 'dcim/rack_import.html' template_name = 'dcim/rack_import.html'
obj_list_url = 'dcim:rack_list' obj_list_url = 'dcim:rack_list'
@ -203,7 +189,7 @@ class RackBulkImportView(PermissionRequiredMixin, BulkImportView):
class RackBulkEditView(PermissionRequiredMixin, BulkEditView): class RackBulkEditView(PermissionRequiredMixin, BulkEditView):
permission_required = 'dcim.change_rack' permission_required = 'dcim.change_rack'
cls = Rack cls = Rack
form = RackBulkEditForm form = forms.RackBulkEditForm
template_name = 'dcim/rack_bulk_edit.html' template_name = 'dcim/rack_bulk_edit.html'
default_redirect_url = 'dcim:rack_list' default_redirect_url = 'dcim:rack_list'
@ -221,7 +207,7 @@ class RackBulkEditView(PermissionRequiredMixin, BulkEditView):
class RackBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class RackBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_rack' permission_required = 'dcim.delete_rack'
cls = Rack cls = Rack
form = RackBulkDeleteForm form = forms.RackBulkDeleteForm
default_redirect_url = 'dcim:rack_list' default_redirect_url = 'dcim:rack_list'
@ -231,7 +217,7 @@ class RackBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class ManufacturerListView(ObjectListView): class ManufacturerListView(ObjectListView):
queryset = Manufacturer.objects.annotate(devicetype_count=Count('device_types')) queryset = Manufacturer.objects.annotate(devicetype_count=Count('device_types'))
table = ManufacturerTable table = tables.ManufacturerTable
edit_permissions = ['dcim.change_manufacturer', 'dcim.delete_manufacturer'] edit_permissions = ['dcim.change_manufacturer', 'dcim.delete_manufacturer']
template_name = 'dcim/manufacturer_list.html' template_name = 'dcim/manufacturer_list.html'
@ -239,7 +225,7 @@ class ManufacturerListView(ObjectListView):
class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView): class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_manufacturer' permission_required = 'dcim.change_manufacturer'
model = Manufacturer model = Manufacturer
form_class = ManufacturerForm form_class = forms.ManufacturerForm
success_url = 'dcim:manufacturer_list' success_url = 'dcim:manufacturer_list'
cancel_url = 'dcim:manufacturer_list' cancel_url = 'dcim:manufacturer_list'
@ -247,7 +233,7 @@ class ManufacturerEditView(PermissionRequiredMixin, ObjectEditView):
class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_manufacturer' permission_required = 'dcim.delete_manufacturer'
cls = Manufacturer cls = Manufacturer
form = ManufacturerBulkDeleteForm form = forms.ManufacturerBulkDeleteForm
default_redirect_url = 'dcim:manufacturer_list' default_redirect_url = 'dcim:manufacturer_list'
@ -257,9 +243,9 @@ class ManufacturerBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class DeviceTypeListView(ObjectListView): class DeviceTypeListView(ObjectListView):
queryset = DeviceType.objects.select_related('manufacturer') queryset = DeviceType.objects.select_related('manufacturer')
filter = DeviceTypeFilter filter = filters.DeviceTypeFilter
filter_form = DeviceTypeFilterForm filter_form = forms.DeviceTypeFilterForm
table = DeviceTypeTable table = tables.DeviceTypeTable
edit_permissions = ['dcim.change_devicetype', 'dcim.delete_devicetype'] edit_permissions = ['dcim.change_devicetype', 'dcim.delete_devicetype']
template_name = 'dcim/devicetype_list.html' template_name = 'dcim/devicetype_list.html'
@ -269,11 +255,12 @@ def devicetype(request, pk):
devicetype = get_object_or_404(DeviceType, pk=pk) devicetype = get_object_or_404(DeviceType, pk=pk)
# Component tables # Component tables
consoleport_table = ConsolePortTemplateTable(ConsolePortTemplate.objects.filter(device_type=devicetype)) consoleport_table = tables.ConsolePortTemplateTable(ConsolePortTemplate.objects.filter(device_type=devicetype))
consoleserverport_table = ConsoleServerPortTemplateTable(ConsoleServerPortTemplate.objects.filter(device_type=devicetype)) consoleserverport_table = tables.ConsoleServerPortTemplateTable(ConsoleServerPortTemplate.objects
powerport_table = PowerPortTemplateTable(PowerPortTemplate.objects.filter(device_type=devicetype)) .filter(device_type=devicetype))
poweroutlet_table = PowerOutletTemplateTable(PowerOutletTemplate.objects.filter(device_type=devicetype)) powerport_table = tables.PowerPortTemplateTable(PowerPortTemplate.objects.filter(device_type=devicetype))
interface_table = InterfaceTemplateTable(InterfaceTemplate.objects.filter(device_type=devicetype)) poweroutlet_table = tables.PowerOutletTemplateTable(PowerOutletTemplate.objects.filter(device_type=devicetype))
interface_table = tables.InterfaceTemplateTable(InterfaceTemplate.objects.filter(device_type=devicetype))
if request.user.has_perm('dcim.change_devicetype'): if request.user.has_perm('dcim.change_devicetype'):
consoleport_table.base_columns['pk'].visible = True consoleport_table.base_columns['pk'].visible = True
consoleserverport_table.base_columns['pk'].visible = True consoleserverport_table.base_columns['pk'].visible = True
@ -294,7 +281,7 @@ def devicetype(request, pk):
class DeviceTypeEditView(PermissionRequiredMixin, ObjectEditView): class DeviceTypeEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_devicetype' permission_required = 'dcim.change_devicetype'
model = DeviceType model = DeviceType
form_class = DeviceTypeForm form_class = forms.DeviceTypeForm
cancel_url = 'dcim:devicetype_list' cancel_url = 'dcim:devicetype_list'
@ -307,7 +294,7 @@ class DeviceTypeDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class DeviceTypeBulkEditView(PermissionRequiredMixin, BulkEditView): class DeviceTypeBulkEditView(PermissionRequiredMixin, BulkEditView):
permission_required = 'dcim.change_devicetype' permission_required = 'dcim.change_devicetype'
cls = DeviceType cls = DeviceType
form = DeviceTypeBulkEditForm form = forms.DeviceTypeBulkEditForm
template_name = 'dcim/devicetype_bulk_edit.html' template_name = 'dcim/devicetype_bulk_edit.html'
default_redirect_url = 'dcim:devicetype_list' default_redirect_url = 'dcim:devicetype_list'
@ -325,7 +312,7 @@ class DeviceTypeBulkEditView(PermissionRequiredMixin, BulkEditView):
class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_devicetype' permission_required = 'dcim.delete_devicetype'
cls = DeviceType cls = DeviceType
form = DeviceTypeBulkDeleteForm form = forms.DeviceTypeBulkDeleteForm
default_redirect_url = 'dcim:devicetype_list' default_redirect_url = 'dcim:devicetype_list'
@ -384,27 +371,27 @@ class ComponentTemplateCreateView(View):
class ConsolePortTemplateAddView(ComponentTemplateCreateView): class ConsolePortTemplateAddView(ComponentTemplateCreateView):
model = ConsolePortTemplate model = ConsolePortTemplate
form = ConsolePortTemplateForm form = forms.ConsolePortTemplateForm
class ConsoleServerPortTemplateAddView(ComponentTemplateCreateView): class ConsoleServerPortTemplateAddView(ComponentTemplateCreateView):
model = ConsoleServerPortTemplate model = ConsoleServerPortTemplate
form = ConsoleServerPortTemplateForm form = forms.ConsoleServerPortTemplateForm
class PowerPortTemplateAddView(ComponentTemplateCreateView): class PowerPortTemplateAddView(ComponentTemplateCreateView):
model = PowerPortTemplate model = PowerPortTemplate
form = PowerPortTemplateForm form = forms.PowerPortTemplateForm
class PowerOutletTemplateAddView(ComponentTemplateCreateView): class PowerOutletTemplateAddView(ComponentTemplateCreateView):
model = PowerOutletTemplate model = PowerOutletTemplate
form = PowerOutletTemplateForm form = forms.PowerOutletTemplateForm
class InterfaceTemplateAddView(ComponentTemplateCreateView): class InterfaceTemplateAddView(ComponentTemplateCreateView):
model = InterfaceTemplate model = InterfaceTemplate
form = InterfaceTemplateForm form = forms.InterfaceTemplateForm
def component_template_delete(request, pk, model): def component_template_delete(request, pk, model):
@ -452,7 +439,7 @@ def component_template_delete(request, pk, model):
class DeviceRoleListView(ObjectListView): class DeviceRoleListView(ObjectListView):
queryset = DeviceRole.objects.annotate(device_count=Count('devices')) queryset = DeviceRole.objects.annotate(device_count=Count('devices'))
table = DeviceRoleTable table = tables.DeviceRoleTable
edit_permissions = ['dcim.change_devicerole', 'dcim.delete_devicerole'] edit_permissions = ['dcim.change_devicerole', 'dcim.delete_devicerole']
template_name = 'dcim/devicerole_list.html' template_name = 'dcim/devicerole_list.html'
@ -460,7 +447,7 @@ class DeviceRoleListView(ObjectListView):
class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView): class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_devicerole' permission_required = 'dcim.change_devicerole'
model = DeviceRole model = DeviceRole
form_class = DeviceRoleForm form_class = forms.DeviceRoleForm
success_url = 'dcim:devicerole_list' success_url = 'dcim:devicerole_list'
cancel_url = 'dcim:devicerole_list' cancel_url = 'dcim:devicerole_list'
@ -468,7 +455,7 @@ class DeviceRoleEditView(PermissionRequiredMixin, ObjectEditView):
class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_devicerole' permission_required = 'dcim.delete_devicerole'
cls = DeviceRole cls = DeviceRole
form = DeviceRoleBulkDeleteForm form = forms.DeviceRoleBulkDeleteForm
default_redirect_url = 'dcim:devicerole_list' default_redirect_url = 'dcim:devicerole_list'
@ -478,7 +465,7 @@ class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class PlatformListView(ObjectListView): class PlatformListView(ObjectListView):
queryset = Platform.objects.annotate(device_count=Count('devices')) queryset = Platform.objects.annotate(device_count=Count('devices'))
table = PlatformTable table = tables.PlatformTable
edit_permissions = ['dcim.change_platform', 'dcim.delete_platform'] edit_permissions = ['dcim.change_platform', 'dcim.delete_platform']
template_name = 'dcim/platform_list.html' template_name = 'dcim/platform_list.html'
@ -486,7 +473,7 @@ class PlatformListView(ObjectListView):
class PlatformEditView(PermissionRequiredMixin, ObjectEditView): class PlatformEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_platform' permission_required = 'dcim.change_platform'
model = Platform model = Platform
form_class = PlatformForm form_class = forms.PlatformForm
success_url = 'dcim:platform_list' success_url = 'dcim:platform_list'
cancel_url = 'dcim:platform_list' cancel_url = 'dcim:platform_list'
@ -494,7 +481,7 @@ class PlatformEditView(PermissionRequiredMixin, ObjectEditView):
class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_platform' permission_required = 'dcim.delete_platform'
cls = Platform cls = Platform
form = PlatformBulkDeleteForm form = forms.PlatformBulkDeleteForm
default_redirect_url = 'dcim:platform_list' default_redirect_url = 'dcim:platform_list'
@ -505,9 +492,9 @@ class PlatformBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class DeviceListView(ObjectListView): class DeviceListView(ObjectListView):
queryset = Device.objects.select_related('device_type', 'device_type__manufacturer', 'device_role', 'rack', queryset = Device.objects.select_related('device_type', 'device_type__manufacturer', 'device_role', 'rack',
'rack__site', 'primary_ip') 'rack__site', 'primary_ip')
filter = DeviceFilter filter = filters.DeviceFilter
filter_form = DeviceFilterForm filter_form = forms.DeviceFilterForm
table = DeviceTable table = tables.DeviceTable
edit_permissions = ['dcim.change_device', 'dcim.delete_device'] edit_permissions = ['dcim.change_device', 'dcim.delete_device']
template_name = 'dcim/device_list.html' template_name = 'dcim/device_list.html'
@ -519,8 +506,10 @@ def device(request, pk):
cs_ports = ConsoleServerPort.objects.filter(device=device).select_related('connected_console') cs_ports = ConsoleServerPort.objects.filter(device=device).select_related('connected_console')
power_ports = PowerPort.objects.filter(device=device).select_related('power_outlet__device') power_ports = PowerPort.objects.filter(device=device).select_related('power_outlet__device')
power_outlets = PowerOutlet.objects.filter(device=device).select_related('connected_port') power_outlets = PowerOutlet.objects.filter(device=device).select_related('connected_port')
interfaces = Interface.objects.filter(device=device, mgmt_only=False).select_related('connected_as_a', 'connected_as_b', 'circuit') interfaces = Interface.objects.filter(device=device, mgmt_only=False)\
mgmt_interfaces = Interface.objects.filter(device=device, mgmt_only=True).select_related('connected_as_a', 'connected_as_b', 'circuit') .select_related('connected_as_a', 'connected_as_b', 'circuit')
mgmt_interfaces = Interface.objects.filter(device=device, mgmt_only=True)\
.select_related('connected_as_a', 'connected_as_b', 'circuit')
# Gather any secrets which belong to this device # Gather any secrets which belong to this device
secrets = device.secrets.all() secrets = device.secrets.all()
@ -540,7 +529,8 @@ def device(request, pk):
else: else:
base_name = None base_name = None
if base_name: if base_name:
related_devices = Device.objects.filter(name__istartswith=base_name).exclude(pk=device.pk).select_related('rack', 'device_type__manufacturer')[:10] related_devices = Device.objects.filter(name__istartswith=base_name).exclude(pk=device.pk)\
.select_related('rack', 'device_type__manufacturer')[:10]
return render(request, 'dcim/device.html', { return render(request, 'dcim/device.html', {
'device': device, 'device': device,
@ -559,7 +549,7 @@ def device(request, pk):
class DeviceEditView(PermissionRequiredMixin, ObjectEditView): class DeviceEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.change_device' permission_required = 'dcim.change_device'
model = Device model = Device
form_class = DeviceForm form_class = forms.DeviceForm
fields_initial = ['site', 'rack', 'position', 'face'] fields_initial = ['site', 'rack', 'position', 'face']
template_name = 'dcim/device_edit.html' template_name = 'dcim/device_edit.html'
cancel_url = 'dcim:device_list' cancel_url = 'dcim:device_list'
@ -573,8 +563,8 @@ class DeviceDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView): class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.add_device' permission_required = 'dcim.add_device'
form = DeviceImportForm form = forms.DeviceImportForm
table = DeviceImportTable table = tables.DeviceImportTable
template_name = 'dcim/device_import.html' template_name = 'dcim/device_import.html'
obj_list_url = 'dcim:device_list' obj_list_url = 'dcim:device_list'
@ -582,7 +572,7 @@ class DeviceBulkImportView(PermissionRequiredMixin, BulkImportView):
class DeviceBulkEditView(PermissionRequiredMixin, BulkEditView): class DeviceBulkEditView(PermissionRequiredMixin, BulkEditView):
permission_required = 'dcim.change_device' permission_required = 'dcim.change_device'
cls = Device cls = Device
form = DeviceBulkEditForm form = forms.DeviceBulkEditForm
template_name = 'dcim/device_bulk_edit.html' template_name = 'dcim/device_bulk_edit.html'
default_redirect_url = 'dcim:device_list' default_redirect_url = 'dcim:device_list'
@ -607,7 +597,7 @@ class DeviceBulkEditView(PermissionRequiredMixin, BulkEditView):
class DeviceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): class DeviceBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'dcim.delete_device' permission_required = 'dcim.delete_device'
cls = Device cls = Device
form = DeviceBulkDeleteForm form = forms.DeviceBulkDeleteForm
default_redirect_url = 'dcim:device_list' default_redirect_url = 'dcim:device_list'
@ -643,12 +633,12 @@ def consoleport_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsolePortCreateForm(request.POST) form = forms.ConsolePortCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
console_ports = [] console_ports = []
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
cp_form = ConsolePortForm({ cp_form = forms.ConsolePortForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
}) })
@ -666,7 +656,7 @@ def consoleport_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = ConsolePortCreateForm() form = forms.ConsolePortCreateForm()
return render(request, 'dcim/consoleport_edit.html', { return render(request, 'dcim/consoleport_edit.html', {
'device': device, 'device': device,
@ -681,7 +671,7 @@ def consoleport_connect(request, pk):
consoleport = get_object_or_404(ConsolePort, pk=pk) consoleport = get_object_or_404(ConsolePort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsolePortConnectionForm(request.POST, instance=consoleport) form = forms.ConsolePortConnectionForm(request.POST, instance=consoleport)
if form.is_valid(): if form.is_valid():
consoleport = form.save() consoleport = form.save()
messages.success(request, "Connected {0} {1} to {2} {3}".format( messages.success(request, "Connected {0} {1} to {2} {3}".format(
@ -693,7 +683,7 @@ def consoleport_connect(request, pk):
return redirect('dcim:device', pk=consoleport.device.pk) return redirect('dcim:device', pk=consoleport.device.pk)
else: else:
form = ConsolePortConnectionForm(instance=consoleport, initial={ form = forms.ConsolePortConnectionForm(instance=consoleport, initial={
'rack': consoleport.device.rack, 'rack': consoleport.device.rack,
'connection_status': CONNECTION_STATUS_CONNECTED, 'connection_status': CONNECTION_STATUS_CONNECTED,
}) })
@ -711,7 +701,8 @@ def consoleport_disconnect(request, pk):
consoleport = get_object_or_404(ConsolePort, pk=pk) consoleport = get_object_or_404(ConsolePort, pk=pk)
if not consoleport.cs_port: if not consoleport.cs_port:
messages.warning(request, "Cannot disconnect console port {0}: It is not connected to anything".format(consoleport)) messages.warning(request, "Cannot disconnect console port {0}: It is not connected to anything"
.format(consoleport))
return redirect('dcim:device', pk=consoleport.device.pk) return redirect('dcim:device', pk=consoleport.device.pk)
if request.method == 'POST': if request.method == 'POST':
@ -739,14 +730,14 @@ def consoleport_edit(request, pk):
consoleport = get_object_or_404(ConsolePort, pk=pk) consoleport = get_object_or_404(ConsolePort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsolePortForm(request.POST, instance=consoleport) form = forms.ConsolePortForm(request.POST, instance=consoleport)
if form.is_valid(): if form.is_valid():
consoleport = form.save() consoleport = form.save()
messages.success(request, "Modified {0} {1}".format(consoleport.device.name, consoleport.name)) messages.success(request, "Modified {0} {1}".format(consoleport.device.name, consoleport.name))
return redirect('dcim:device', pk=consoleport.device.pk) return redirect('dcim:device', pk=consoleport.device.pk)
else: else:
form = ConsolePortForm(instance=consoleport) form = forms.ConsolePortForm(instance=consoleport)
return render(request, 'dcim/consoleport_edit.html', { return render(request, 'dcim/consoleport_edit.html', {
'consoleport': consoleport, 'consoleport': consoleport,
@ -764,7 +755,8 @@ def consoleport_delete(request, pk):
form = ConfirmationForm(request.POST) form = ConfirmationForm(request.POST)
if form.is_valid(): if form.is_valid():
consoleport.delete() consoleport.delete()
messages.success(request, "Console port {0} has been deleted from {1}".format(consoleport, consoleport.device)) messages.success(request, "Console port {0} has been deleted from {1}".format(consoleport,
consoleport.device))
return redirect('dcim:device', pk=consoleport.device.pk) return redirect('dcim:device', pk=consoleport.device.pk)
else: else:
@ -779,8 +771,8 @@ def consoleport_delete(request, pk):
class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView): class ConsoleConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_consoleport' permission_required = 'dcim.change_consoleport'
form = ConsoleConnectionImportForm form = forms.ConsoleConnectionImportForm
table = ConsoleConnectionTable table = tables.ConsoleConnectionTable
template_name = 'dcim/console_connections_import.html' template_name = 'dcim/console_connections_import.html'
@ -794,12 +786,12 @@ def consoleserverport_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsoleServerPortCreateForm(request.POST) form = forms.ConsoleServerPortCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
cs_ports = [] cs_ports = []
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
csp_form = ConsoleServerPortForm({ csp_form = forms.ConsoleServerPortForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
}) })
@ -818,7 +810,7 @@ def consoleserverport_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = ConsoleServerPortCreateForm() form = forms.ConsoleServerPortCreateForm()
return render(request, 'dcim/consoleserverport_edit.html', { return render(request, 'dcim/consoleserverport_edit.html', {
'device': device, 'device': device,
@ -833,7 +825,7 @@ def consoleserverport_connect(request, pk):
consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk) consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsoleServerPortConnectionForm(consoleserverport, request.POST) form = forms.ConsoleServerPortConnectionForm(consoleserverport, request.POST)
if form.is_valid(): if form.is_valid():
consoleport = form.cleaned_data['port'] consoleport = form.cleaned_data['port']
consoleport.cs_port = consoleserverport consoleport.cs_port = consoleserverport
@ -848,7 +840,7 @@ def consoleserverport_connect(request, pk):
return redirect('dcim:device', pk=consoleserverport.device.pk) return redirect('dcim:device', pk=consoleserverport.device.pk)
else: else:
form = ConsoleServerPortConnectionForm(consoleserverport, initial={'rack': consoleserverport.device.rack}) form = forms.ConsoleServerPortConnectionForm(consoleserverport, initial={'rack': consoleserverport.device.rack})
return render(request, 'dcim/consoleserverport_connect.html', { return render(request, 'dcim/consoleserverport_connect.html', {
'consoleserverport': consoleserverport, 'consoleserverport': consoleserverport,
@ -863,7 +855,8 @@ def consoleserverport_disconnect(request, pk):
consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk) consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk)
if not hasattr(consoleserverport, 'connected_console'): if not hasattr(consoleserverport, 'connected_console'):
messages.warning(request, "Cannot disconnect console server port {0}: Nothing is connected to it".format(consoleserverport)) messages.warning(request, "Cannot disconnect console server port {0}: Nothing is connected to it"
.format(consoleserverport))
return redirect('dcim:device', pk=consoleserverport.device.pk) return redirect('dcim:device', pk=consoleserverport.device.pk)
if request.method == 'POST': if request.method == 'POST':
@ -892,14 +885,14 @@ def consoleserverport_edit(request, pk):
consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk) consoleserverport = get_object_or_404(ConsoleServerPort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = ConsoleServerPortForm(request.POST, instance=consoleserverport) form = forms.ConsoleServerPortForm(request.POST, instance=consoleserverport)
if form.is_valid(): if form.is_valid():
consoleserverport = form.save() consoleserverport = form.save()
messages.success(request, "Modified {0} {1}".format(consoleserverport.device.name, consoleserverport.name)) messages.success(request, "Modified {0} {1}".format(consoleserverport.device.name, consoleserverport.name))
return redirect('dcim:device', pk=consoleserverport.device.pk) return redirect('dcim:device', pk=consoleserverport.device.pk)
else: else:
form = ConsoleServerPortForm(instance=consoleserverport) form = forms.ConsoleServerPortForm(instance=consoleserverport)
return render(request, 'dcim/consoleserverport_edit.html', { return render(request, 'dcim/consoleserverport_edit.html', {
'consoleserverport': consoleserverport, 'consoleserverport': consoleserverport,
@ -917,7 +910,8 @@ def consoleserverport_delete(request, pk):
form = ConfirmationForm(request.POST) form = ConfirmationForm(request.POST)
if form.is_valid(): if form.is_valid():
consoleserverport.delete() consoleserverport.delete()
messages.success(request, "Console server port {0} has been deleted from {1}".format(consoleserverport, consoleserverport.device)) messages.success(request, "Console server port {0} has been deleted from {1}"
.format(consoleserverport, consoleserverport.device))
return redirect('dcim:device', pk=consoleserverport.device.pk) return redirect('dcim:device', pk=consoleserverport.device.pk)
else: else:
@ -940,12 +934,12 @@ def powerport_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerPortCreateForm(request.POST) form = forms.PowerPortCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
power_ports = [] power_ports = []
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
pp_form = PowerPortForm({ pp_form = forms.PowerPortForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
}) })
@ -963,7 +957,7 @@ def powerport_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = PowerPortCreateForm() form = forms.PowerPortCreateForm()
return render(request, 'dcim/powerport_edit.html', { return render(request, 'dcim/powerport_edit.html', {
'device': device, 'device': device,
@ -978,7 +972,7 @@ def powerport_connect(request, pk):
powerport = get_object_or_404(PowerPort, pk=pk) powerport = get_object_or_404(PowerPort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerPortConnectionForm(request.POST, instance=powerport) form = forms.PowerPortConnectionForm(request.POST, instance=powerport)
if form.is_valid(): if form.is_valid():
powerport = form.save() powerport = form.save()
messages.success(request, "Connected {0} {1} to {2} {3}".format( messages.success(request, "Connected {0} {1} to {2} {3}".format(
@ -990,7 +984,7 @@ def powerport_connect(request, pk):
return redirect('dcim:device', pk=powerport.device.pk) return redirect('dcim:device', pk=powerport.device.pk)
else: else:
form = PowerPortConnectionForm(instance=powerport, initial={ form = forms.PowerPortConnectionForm(instance=powerport, initial={
'rack': powerport.device.rack, 'rack': powerport.device.rack,
'connection_status': CONNECTION_STATUS_CONNECTED, 'connection_status': CONNECTION_STATUS_CONNECTED,
}) })
@ -1008,7 +1002,8 @@ def powerport_disconnect(request, pk):
powerport = get_object_or_404(PowerPort, pk=pk) powerport = get_object_or_404(PowerPort, pk=pk)
if not powerport.power_outlet: if not powerport.power_outlet:
messages.warning(request, "Cannot disconnect power port {0}: It is not connected to an outlet".format(powerport)) messages.warning(request, "Cannot disconnect power port {0}: It is not connected to an outlet"
.format(powerport))
return redirect('dcim:device', pk=powerport.device.pk) return redirect('dcim:device', pk=powerport.device.pk)
if request.method == 'POST': if request.method == 'POST':
@ -1036,14 +1031,14 @@ def powerport_edit(request, pk):
powerport = get_object_or_404(PowerPort, pk=pk) powerport = get_object_or_404(PowerPort, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerPortForm(request.POST, instance=powerport) form = forms.PowerPortForm(request.POST, instance=powerport)
if form.is_valid(): if form.is_valid():
powerport = form.save() powerport = form.save()
messages.success(request, "Modified {0} power port {1}".format(powerport.device.name, powerport.name)) messages.success(request, "Modified {0} power port {1}".format(powerport.device.name, powerport.name))
return redirect('dcim:device', pk=powerport.device.pk) return redirect('dcim:device', pk=powerport.device.pk)
else: else:
form = PowerPortForm(instance=powerport) form = forms.PowerPortForm(instance=powerport)
return render(request, 'dcim/powerport_edit.html', { return render(request, 'dcim/powerport_edit.html', {
'powerport': powerport, 'powerport': powerport,
@ -1076,8 +1071,8 @@ def powerport_delete(request, pk):
class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView): class PowerConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_powerport' permission_required = 'dcim.change_powerport'
form = PowerConnectionImportForm form = forms.PowerConnectionImportForm
table = PowerConnectionTable table = tables.PowerConnectionTable
template_name = 'dcim/power_connections_import.html' template_name = 'dcim/power_connections_import.html'
@ -1091,12 +1086,12 @@ def poweroutlet_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerOutletCreateForm(request.POST) form = forms.PowerOutletCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
power_outlets = [] power_outlets = []
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
po_form = PowerOutletForm({ po_form = forms.PowerOutletForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
}) })
@ -1114,7 +1109,7 @@ def poweroutlet_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = PowerOutletCreateForm() form = forms.PowerOutletCreateForm()
return render(request, 'dcim/poweroutlet_edit.html', { return render(request, 'dcim/poweroutlet_edit.html', {
'device': device, 'device': device,
@ -1129,7 +1124,7 @@ def poweroutlet_connect(request, pk):
poweroutlet = get_object_or_404(PowerOutlet, pk=pk) poweroutlet = get_object_or_404(PowerOutlet, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerOutletConnectionForm(poweroutlet, request.POST) form = forms.PowerOutletConnectionForm(poweroutlet, request.POST)
if form.is_valid(): if form.is_valid():
powerport = form.cleaned_data['port'] powerport = form.cleaned_data['port']
powerport.power_outlet = poweroutlet powerport.power_outlet = poweroutlet
@ -1144,7 +1139,7 @@ def poweroutlet_connect(request, pk):
return redirect('dcim:device', pk=poweroutlet.device.pk) return redirect('dcim:device', pk=poweroutlet.device.pk)
else: else:
form = PowerOutletConnectionForm(poweroutlet, initial={'rack': poweroutlet.device.rack}) form = forms.PowerOutletConnectionForm(poweroutlet, initial={'rack': poweroutlet.device.rack})
return render(request, 'dcim/poweroutlet_connect.html', { return render(request, 'dcim/poweroutlet_connect.html', {
'poweroutlet': poweroutlet, 'poweroutlet': poweroutlet,
@ -1188,14 +1183,14 @@ def poweroutlet_edit(request, pk):
poweroutlet = get_object_or_404(PowerOutlet, pk=pk) poweroutlet = get_object_or_404(PowerOutlet, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = PowerOutletForm(request.POST, instance=poweroutlet) form = forms.PowerOutletForm(request.POST, instance=poweroutlet)
if form.is_valid(): if form.is_valid():
poweroutlet = form.save() poweroutlet = form.save()
messages.success(request, "Modified {0} power outlet {1}".format(poweroutlet.device.name, poweroutlet.name)) messages.success(request, "Modified {0} power outlet {1}".format(poweroutlet.device.name, poweroutlet.name))
return redirect('dcim:device', pk=poweroutlet.device.pk) return redirect('dcim:device', pk=poweroutlet.device.pk)
else: else:
form = PowerOutletForm(instance=poweroutlet) form = forms.PowerOutletForm(instance=poweroutlet)
return render(request, 'dcim/poweroutlet_edit.html', { return render(request, 'dcim/poweroutlet_edit.html', {
'poweroutlet': poweroutlet, 'poweroutlet': poweroutlet,
@ -1213,7 +1208,8 @@ def poweroutlet_delete(request, pk):
form = ConfirmationForm(request.POST) form = ConfirmationForm(request.POST)
if form.is_valid(): if form.is_valid():
poweroutlet.delete() poweroutlet.delete()
messages.success(request, "Power outlet {0} has been deleted from {1}".format(poweroutlet, poweroutlet.device)) messages.success(request, "Power outlet {0} has been deleted from {1}".format(poweroutlet,
poweroutlet.device))
return redirect('dcim:device', pk=poweroutlet.device.pk) return redirect('dcim:device', pk=poweroutlet.device.pk)
else: else:
@ -1236,12 +1232,12 @@ def interface_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = InterfaceCreateForm(request.POST) form = forms.InterfaceCreateForm(request.POST)
if form.is_valid(): if form.is_valid():
interfaces = [] interfaces = []
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
iface_form = InterfaceForm({ iface_form = forms.InterfaceForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
'form_factor': form.cleaned_data['form_factor'], 'form_factor': form.cleaned_data['form_factor'],
@ -1262,7 +1258,7 @@ def interface_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = InterfaceCreateForm() form = forms.InterfaceCreateForm()
return render(request, 'dcim/interface_edit.html', { return render(request, 'dcim/interface_edit.html', {
'device': device, 'device': device,
@ -1277,14 +1273,14 @@ def interface_edit(request, pk):
interface = get_object_or_404(Interface, pk=pk) interface = get_object_or_404(Interface, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = InterfaceForm(request.POST, instance=interface) form = forms.InterfaceForm(request.POST, instance=interface)
if form.is_valid(): if form.is_valid():
interface = form.save() interface = form.save()
messages.success(request, "Modified {0} interface {1}".format(interface.device.name, interface.name)) messages.success(request, "Modified {0} interface {1}".format(interface.device.name, interface.name))
return redirect('dcim:device', pk=interface.device.pk) return redirect('dcim:device', pk=interface.device.pk)
else: else:
form = InterfaceForm(instance=interface) form = forms.InterfaceForm(instance=interface)
return render(request, 'dcim/interface_edit.html', { return render(request, 'dcim/interface_edit.html', {
'interface': interface, 'interface': interface,
@ -1318,7 +1314,7 @@ def interface_delete(request, pk):
class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView): class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
permission_required = 'dcim.add_interface' permission_required = 'dcim.add_interface'
cls = Device cls = Device
form = InterfaceBulkCreateForm form = forms.InterfaceBulkCreateForm
template_name = 'dcim/interface_bulk_add.html' template_name = 'dcim/interface_bulk_add.html'
default_redirect_url = 'dcim:device_list' default_redirect_url = 'dcim:device_list'
@ -1329,7 +1325,7 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
for device in selected_devices: for device in selected_devices:
for name in form.cleaned_data['name_pattern']: for name in form.cleaned_data['name_pattern']:
iface_form = InterfaceForm({ iface_form = forms.InterfaceForm({
'device': device.pk, 'device': device.pk,
'name': name, 'name': name,
'form_factor': form.cleaned_data['form_factor'], 'form_factor': form.cleaned_data['form_factor'],
@ -1357,7 +1353,7 @@ def interfaceconnection_add(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = InterfaceConnectionForm(device, request.POST) form = forms.InterfaceConnectionForm(device, request.POST)
if form.is_valid(): if form.is_valid():
interfaceconnection = form.save() interfaceconnection = form.save()
messages.success(request, "Connected {0} {1} to {2} {3}".format( messages.success(request, "Connected {0} {1} to {2} {3}".format(
@ -1377,7 +1373,7 @@ def interfaceconnection_add(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = InterfaceConnectionForm(device, initial={ form = forms.InterfaceConnectionForm(device, initial={
'interface_a': request.GET.get('interface', None), 'interface_a': request.GET.get('interface', None),
'rack_b': request.GET.get('rack_b', None), 'rack_b': request.GET.get('rack_b', None),
'device_b': request.GET.get('device_b', None), 'device_b': request.GET.get('device_b', None),
@ -1397,7 +1393,7 @@ def interfaceconnection_delete(request, pk):
device_id = request.GET.get('device', None) device_id = request.GET.get('device', None)
if request.method == 'POST': if request.method == 'POST':
form = InterfaceConnectionDeletionForm(request.POST) form = forms.InterfaceConnectionDeletionForm(request.POST)
if form.is_valid(): if form.is_valid():
interfaceconnection.delete() interfaceconnection.delete()
messages.success(request, "Deleted the connection between {0} {1} and {2} {3}".format( messages.success(request, "Deleted the connection between {0} {1} and {2} {3}".format(
@ -1412,7 +1408,7 @@ def interfaceconnection_delete(request, pk):
return redirect('dcim:device_list') return redirect('dcim:device_list')
else: else:
form = InterfaceConnectionDeletionForm(initial={ form = forms.InterfaceConnectionDeletionForm(initial={
'device': device_id, 'device': device_id,
}) })
@ -1432,8 +1428,8 @@ def interfaceconnection_delete(request, pk):
class InterfaceConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView): class InterfaceConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_interface' permission_required = 'dcim.change_interface'
form = InterfaceConnectionImportForm form = forms.InterfaceConnectionImportForm
table = InterfaceConnectionTable table = tables.InterfaceConnectionTable
template_name = 'dcim/interface_connections_import.html' template_name = 'dcim/interface_connections_import.html'
@ -1444,27 +1440,27 @@ class InterfaceConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView
class ConsoleConnectionsListView(ObjectListView): class ConsoleConnectionsListView(ObjectListView):
queryset = ConsolePort.objects.select_related('device', 'cs_port__device').filter(cs_port__isnull=False)\ queryset = ConsolePort.objects.select_related('device', 'cs_port__device').filter(cs_port__isnull=False)\
.order_by('cs_port__device__name', 'cs_port__name') .order_by('cs_port__device__name', 'cs_port__name')
filter = ConsoleConnectionFilter filter = filters.ConsoleConnectionFilter
filter_form = ConsoleConnectionFilterForm filter_form = forms.ConsoleConnectionFilterForm
table = ConsoleConnectionTable table = tables.ConsoleConnectionTable
template_name = 'dcim/console_connections_list.html' template_name = 'dcim/console_connections_list.html'
class PowerConnectionsListView(ObjectListView): class PowerConnectionsListView(ObjectListView):
queryset = PowerPort.objects.select_related('device', 'power_outlet__device').filter(power_outlet__isnull=False)\ queryset = PowerPort.objects.select_related('device', 'power_outlet__device').filter(power_outlet__isnull=False)\
.order_by('power_outlet__device__name', 'power_outlet__name') .order_by('power_outlet__device__name', 'power_outlet__name')
filter = PowerConnectionFilter filter = filters.PowerConnectionFilter
filter_form = PowerConnectionFilterForm filter_form = forms.PowerConnectionFilterForm
table = PowerConnectionTable table = tables.PowerConnectionTable
template_name = 'dcim/power_connections_list.html' template_name = 'dcim/power_connections_list.html'
class InterfaceConnectionsListView(ObjectListView): class InterfaceConnectionsListView(ObjectListView):
queryset = InterfaceConnection.objects.select_related('interface_a__device', 'interface_b__device')\ queryset = InterfaceConnection.objects.select_related('interface_a__device', 'interface_b__device')\
.order_by('interface_a__device__name', 'interface_a__name') .order_by('interface_a__device__name', 'interface_a__name')
filter = InterfaceConnectionFilter filter = filters.InterfaceConnectionFilter
filter_form = InterfaceConnectionFilterForm filter_form = forms.InterfaceConnectionFilterForm
table = InterfaceConnectionTable table = tables.InterfaceConnectionTable
template_name = 'dcim/interface_connections_list.html' template_name = 'dcim/interface_connections_list.html'
@ -1478,13 +1474,14 @@ def ipaddress_assign(request, pk):
device = get_object_or_404(Device, pk=pk) device = get_object_or_404(Device, pk=pk)
if request.method == 'POST': if request.method == 'POST':
form = IPAddressForm(device, request.POST) form = forms.IPAddressForm(device, request.POST)
if form.is_valid(): if form.is_valid():
ipaddress = form.save(commit=False) ipaddress = form.save(commit=False)
ipaddress.interface = form.cleaned_data['interface'] ipaddress.interface = form.cleaned_data['interface']
ipaddress.save() ipaddress.save()
messages.success(request, "Added new IP address {0} to interface {1}".format(ipaddress, ipaddress.interface)) messages.success(request, "Added new IP address {0} to interface {1}".format(ipaddress,
ipaddress.interface))
if form.cleaned_data['set_as_primary']: if form.cleaned_data['set_as_primary']:
device.primary_ip = ipaddress device.primary_ip = ipaddress
@ -1496,7 +1493,7 @@ def ipaddress_assign(request, pk):
return redirect('dcim:device', pk=device.pk) return redirect('dcim:device', pk=device.pk)
else: else:
form = IPAddressForm(device) form = forms.IPAddressForm(device)
return render(request, 'dcim/ipaddress_assign.html', { return render(request, 'dcim/ipaddress_assign.html', {
'device': device, 'device': device,