Browse Source

Added views to create device component templates

Jeremy Stretch 9 years ago
parent
commit
009ef41e92

+ 46 - 1
netbox/dcim/forms.py

@@ -8,7 +8,8 @@ from utilities.forms import BootstrapMixin, SmallTextarea, SelectWithDisabled, C
     Livesearch, CSVDataField, CommentField, BulkImportForm, FlexibleModelChoiceField, ExpandableNameField
 
 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
 
 
@@ -192,6 +193,50 @@ class DeviceTypeFilterForm(forms.Form, BootstrapMixin):
 
 
 #
+# 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
 #
 

+ 12 - 0
netbox/dcim/urls.py

@@ -3,6 +3,8 @@ from django.conf.urls import url
 from secrets.views import secret_add
 
 from . import views
+from .forms import ConsolePortTemplateForm
+
 
 urlpatterns = [
 
@@ -32,6 +34,16 @@ urlpatterns = [
     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+)/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
     url(r'^devices/$', views.DeviceListView.as_view(), name='device_list'),

+ 80 - 2
netbox/dcim/views.py

@@ -3,11 +3,13 @@ import re
 from django.contrib import messages
 from django.contrib.auth.decorators import permission_required
 from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse
 from django.db.models import Count, ProtectedError
 from django.http import HttpResponseRedirect
 from django.shortcuts import get_object_or_404, redirect, render
 from django.utils.http import urlencode
+from django.views.generic import View
 
 from ipam.models import Prefix, IPAddress, VLAN
 from circuits.models import Circuit
@@ -25,8 +27,10 @@ from .forms import SiteForm, SiteImportForm, RackForm, RackImportForm, RackBulkE
     PowerPortCreateForm, PowerPortConnectionForm, PowerConnectionImportForm, PowerOutletForm, PowerOutletCreateForm, \
     PowerOutletConnectionForm, InterfaceForm, InterfaceCreateForm, InterfaceBulkCreateForm, InterfaceConnectionForm, \
     InterfaceConnectionDeletionForm, InterfaceConnectionImportForm, ConsoleConnectionFilterForm, \
-    PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm
-from .models import Site, Rack, DeviceType, Device, ConsolePort, ConsoleServerPort, PowerPort, PowerOutlet, Interface, \
+    PowerConnectionFilterForm, InterfaceConnectionFilterForm, IPAddressForm, ConsolePortTemplateForm, \
+    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
 from .tables import SiteTable, RackTable, RackBulkEditTable, DeviceTypeTable, DeviceTypeBulkEditTable, DeviceTable, \
     DeviceBulkEditTable, DeviceImportTable, ConsoleConnectionTable, PowerConnectionTable, InterfaceConnectionTable
@@ -428,6 +432,80 @@ class DeviceTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
     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
 #

+ 42 - 0
netbox/templates/dcim/component_template_add.html

@@ -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 %}

+ 15 - 0
netbox/templates/dcim/devicetype.html

@@ -75,6 +75,9 @@
         </div>
         <div class="panel panel-default">
             <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>
             </div>
             <table class="table table-hover panel-body">
@@ -88,6 +91,9 @@
         </div>
         <div class="panel panel-default">
             <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>
             </div>
             <table class="table table-hover panel-body">
@@ -103,6 +109,9 @@
 	<div class="col-md-6">
         <div class="panel panel-default">
             <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>
             </div>
             <table class="table table-hover panel-body">
@@ -118,6 +127,9 @@
         </div>
         <div class="panel panel-default">
             <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>
             </div>
             <table class="table table-hover panel-body">
@@ -131,6 +143,9 @@
         </div>
         <div class="panel panel-default">
             <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>
             </div>
             <table class="table table-hover panel-body">