Added views to create device component templates

This commit is contained in:
Jeremy Stretch 2016-03-04 16:41:24 -05:00
parent 082445c016
commit 009ef41e92
5 changed files with 195 additions and 3 deletions

View File

@ -8,7 +8,8 @@ from utilities.forms import BootstrapMixin, SmallTextarea, SelectWithDisabled, C
Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField
from .models import Site, Rack, RackGroup, Device, Manufacturer, DeviceType, DeviceRole, Platform, ConsolePort, \ from .models import Site, Rack, RackGroup, Device, Manufacturer, DeviceType, DeviceRole, Platform, ConsolePort, \
ConsoleServerPort, PowerPort, PowerOutlet, Interface, InterfaceConnection, CONNECTION_STATUS_CHOICES, \ ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, PowerPort, PowerPortTemplate, PowerOutlet, \
PowerOutletTemplate, Interface, InterfaceTemplate, InterfaceConnection, CONNECTION_STATUS_CHOICES, \
CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, IFACE_FF_VIRTUAL, STATUS_CHOICES CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED, IFACE_FF_VIRTUAL, STATUS_CHOICES
@ -191,6 +192,50 @@ class DeviceTypeFilterForm(forms.Form, BootstrapMixin):
widget=forms.SelectMultiple(attrs={'size': 8})) widget=forms.SelectMultiple(attrs={'size': 8}))
#
# Device component templates
#
class ConsolePortTemplateForm(forms.ModelForm, BootstrapMixin):
name_pattern = ExpandableNameField(label='Name')
class Meta:
model = ConsolePortTemplate
fields = ['name_pattern']
class ConsoleServerPortTemplateForm(forms.ModelForm, BootstrapMixin):
name_pattern = ExpandableNameField(label='Name')
class Meta:
model = ConsoleServerPortTemplate
fields = ['name_pattern']
class PowerPortTemplateForm(forms.ModelForm, BootstrapMixin):
name_pattern = ExpandableNameField(label='Name')
class Meta:
model = PowerPortTemplate
fields = ['name_pattern']
class PowerOutletTemplateForm(forms.ModelForm, BootstrapMixin):
name_pattern = ExpandableNameField(label='Name')
class Meta:
model = PowerOutletTemplate
fields = ['name_pattern']
class InterfaceTemplateForm(forms.ModelForm, BootstrapMixin):
name_pattern = ExpandableNameField(label='Name')
class Meta:
model = InterfaceTemplate
fields = ['name_pattern', 'form_factor', 'mgmt_only']
# #
# Devices # Devices
# #

View File

@ -3,6 +3,8 @@ 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 .forms import ConsolePortTemplateForm
urlpatterns = [ urlpatterns = [
@ -32,6 +34,16 @@ urlpatterns = [
url(r'^device-types/(?P<pk>\d+)/$', views.devicetype, name='devicetype'), url(r'^device-types/(?P<pk>\d+)/$', views.devicetype, name='devicetype'),
url(r'^device-types/(?P<pk>\d+)/edit/$', views.devicetype_edit, name='devicetype_edit'), url(r'^device-types/(?P<pk>\d+)/edit/$', views.devicetype_edit, name='devicetype_edit'),
url(r'^device-types/(?P<pk>\d+)/delete/$', views.devicetype_delete, name='devicetype_delete'), url(r'^device-types/(?P<pk>\d+)/delete/$', views.devicetype_delete, name='devicetype_delete'),
url(r'^device-types/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortTemplateAddView.as_view(),
name='devicetype_add_consoleport'),
url(r'^device-types/(?P<pk>\d+)/console-server-ports/add/$', views.ConsolePortTemplateAddView.as_view(),
name='devicetype_add_consoleserverport'),
url(r'^device-types/(?P<pk>\d+)/power-ports/add/$', views.PowerPortTemplateAddView.as_view(),
name='devicetype_add_powerport'),
url(r'^device-types/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletTemplateAddView.as_view(),
name='devicetype_add_poweroutlet'),
url(r'^device-types/(?P<pk>\d+)/interfaces/add/$', views.InterfaceTemplateAddView.as_view(),
name='devicetype_add_interface'),
# Devices # Devices
url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'), url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),

View File

@ -3,11 +3,13 @@ import re
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import permission_required from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ValidationError
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db.models import Count, ProtectedError from django.db.models import Count, ProtectedError
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.utils.http import urlencode from django.utils.http import urlencode
from django.views.generic import View
from ipam.models import Prefix, IPAddress, VLAN from ipam.models import Prefix, IPAddress, VLAN
from circuits.models import Circuit from circuits.models import Circuit
@ -25,8 +27,10 @@ from .forms import SiteForm, SiteImportForm, RackForm, RackImportForm, RackBulkE
PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \ PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \ PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \ InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, ConsolePortTemplateForm, \
from .models import Site, Rack, DeviceType, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \ ConsoleServerPortTemplateForm, PowerPortTemplateForm, PowerOutletTemplateForm, InterfaceTemplateForm
from .models import Site, Rack, DeviceType, ConsolePortTemplate, ConsoleServerPortTemplate, PowerPortTemplate, \
PowerOutletTemplate, InterfaceTemplate, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED InterfaceConnection, Module, CONNECTION_STATUS_CONNECTED
from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \ from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable
@ -428,6 +432,80 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
redirect_url = 'dcim:devicetype_list' redirect_url = 'dcim:devicetype_list'
class ComponentTemplateCreateView(View):
model = None
form = None
def get(self, request, pk, *args, **kwargs):
devicetype = get_object_or_404(DeviceType, pk=pk)
return render(request, 'dcim/component_template_add.html', {
'devicetype': devicetype,
'component_type': self.model._meta.verbose_name,
'form': self.form(),
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
})
def post(self, request, pk, *args, **kwargs):
devicetype = get_object_or_404(DeviceType, pk=pk)
form = self.form(request.POST)
if form.is_valid():
component_templates = []
for name in form.cleaned_data['name_pattern']:
component_template = self.form(request.POST).save(commit=False)
component_template.device_type = devicetype
component_template.name = name
try:
component_template.full_clean()
component_templates.append(component_template)
except ValidationError:
form.add_error('name_pattern', "Duplicate name found: {}".format(name))
if not form.errors:
self.model.objects.bulk_create(component_templates)
messages.success(request, "Added {} compontent(s) to {}".format(len(component_templates), devicetype))
if '_addanother' in request.POST:
return redirect(request.path)
else:
return redirect('dcim:devicetype', pk=devicetype.pk)
return render(request, 'dcim/component_template_add.html', {
'devicetype': devicetype,
'component_type': self.model._meta.verbose_name,
'form': form,
'cancel_url': reverse('dcim:devicetype', kwargs={'pk': devicetype.pk}),
})
class ConsolePortTemplateAddView(ComponentTemplateCreateView):
model = ConsolePortTemplate
form = ConsolePortTemplateForm
class ConsoleServerPortTemplateAddView(ComponentTemplateCreateView):
model = ConsoleServerPortTemplate
form = ConsoleServerPortTemplateForm
class PowerPortTemplateAddView(ComponentTemplateCreateView):
model = PowerPortTemplate
form = PowerPortTemplateForm
class PowerOutletTemplateAddView(ComponentTemplateCreateView):
model = PowerOutletTemplate
form = PowerOutletTemplateForm
class InterfaceTemplateAddView(ComponentTemplateCreateView):
model = InterfaceTemplate
form = InterfaceTemplateForm
# #
# Devices # Devices
# #

View File

@ -0,0 +1,42 @@
{% extends '_base.html' %}
{% load form_helpers %}
{% block title %}Add {{ component_type }} to {{ devicetype }}{% endblock %}
{% block content %}
<form action="." method="post" class="form form-horizontal">
{% csrf_token %}
<div class="row">
<div class="col-md-6 col-md-offset-3">
{% if form.non_field_errors %}
<div class="panel panel-danger">
<div class="panel-heading"><strong>Errors</strong></div>
<div class="panel-body">
{{ form.non_field_errors }}
</div>
</div>
{% endif %}
<div class="panel panel-default">
<div class="panel-heading">
<strong>New {{ component_type }}</strong>
</div>
<div class="panel-body">
<div class="form-group">
<label class="col-md-3 control-label required">Device Type</label>
<div class="col-md-9">
<p class="form-control-static">{{ devicetype }}</p>
</div>
</div>
{% render_form form %}
</div>
</div>
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<button type="submit" name="_update" class="btn btn-primary">Save</button>
<a href="{{ cancel_url }}" class="btn btn-default">Cancel</a>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -75,6 +75,9 @@
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% if perms.dcim.change_devicetype %}
<a href="{% url 'dcim:devicetype_add_consoleport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Console Ports</a>
{% endif %}
<strong>Console Ports</strong> <strong>Console Ports</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
@ -88,6 +91,9 @@
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% if perms.dcim.change_devicetype %}
<a href="{% url 'dcim:devicetype_add_powerport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Power Ports</a>
{% endif %}
<strong>Power Ports</strong> <strong>Power Ports</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
@ -103,6 +109,9 @@
<div class="col-md-6"> <div class="col-md-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% if perms.dcim.change_devicetype %}
<a href="{% url 'dcim:devicetype_add_interface' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Interfaces</a>
{% endif %}
<strong>Interfaces</strong> <strong>Interfaces</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
@ -118,6 +127,9 @@
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% if perms.dcim.change_devicetype %}
<a href="{% url 'dcim:devicetype_add_consoleserverport' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Console Server Ports</a>
{% endif %}
<strong>Console Server Ports</strong> <strong>Console Server Ports</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">
@ -131,6 +143,9 @@
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
{% if perms.dcim.change_devicetype %}
<a href="{% url 'dcim:devicetype_add_poweroutlet' pk=devicetype.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Power Outlet</a>
{% endif %}
<strong>Power Outlets</strong> <strong>Power Outlets</strong>
</div> </div>
<table class="table table-hover panel-body"> <table class="table table-hover panel-body">