From 974d8419e68edc58123c5648ef301bb4cbebd9d5 Mon Sep 17 00:00:00 2001 From: Iva Kaneva Date: Sat, 1 Oct 2016 20:47:48 +0300 Subject: [PATCH] Add "Add ServicePort" functionality --- netbox/dcim/forms.py | 24 +++++++++++- netbox/dcim/urls.py | 1 + netbox/dcim/views.py | 31 +++++++++++++++- netbox/ipam/forms.py | 20 +++++++++- netbox/ipam/urls.py | 3 ++ netbox/ipam/views.py | 14 ++++++- netbox/templates/dcim/device.html | 8 ++++ netbox/templates/dcim/serviceport_assign.html | 37 +++++++++++++++++++ 8 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 netbox/templates/dcim/serviceport_assign.html diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index 44e30e964..a1441eb4b 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError from django.db.models import Count, Q from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm -from ipam.models import IPAddress +from ipam.models import IPAddress, ServicePort from tenancy.models import Tenant from utilities.forms import ( APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField, CSVDataField, @@ -1265,6 +1265,28 @@ class IPAddressForm(BootstrapMixin, CustomFieldForm): self.fields['set_as_primary'].initial = True +# +# Service Port +# + +class ServicePortForm(forms.ModelForm, BootstrapMixin): + + class Meta: + model = ServicePort + fields = ['ip_address', 'type', 'port', 'name', 'description'] + help_texts = { + 'port': '0-65535', + 'name': 'Service running on this port', + 'description': 'Service description' + } + labels = { + 'ip_address': "IP Address", + } + + def __init__(self, device, *args, **kwargs): + super(ServicePortForm, self).__init__(*args, **kwargs) + self.fields['ip_address'].queryset = IPAddress.objects.filter(interface__device=device) + # # Modules # diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 3ec018116..39ab88a90 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -103,6 +103,7 @@ urlpatterns = [ url(r'^devices/(?P\d+)/inventory/$', views.device_inventory, name='device_inventory'), url(r'^devices/(?P\d+)/lldp-neighbors/$', views.device_lldp_neighbors, name='device_lldp_neighbors'), url(r'^devices/(?P\d+)/ip-addresses/assign/$', views.ipaddress_assign, name='ipaddress_assign'), + url(r'^devices/(?P\d+)/service-ports/assign/$', views.serviceport_assign, name='serviceport_assign'), url(r'^devices/(?P\d+)/add-secret/$', secret_add, name='device_addsecret'), # Console ports diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index d31670446..3ef706725 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -15,7 +15,7 @@ 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 ipam.models import Prefix, IPAddress, VLAN, ServicePort from circuits.models import Circuit from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE from utilities.forms import ConfirmationForm @@ -576,6 +576,7 @@ def device(request, pk): # Find all IP addresses assigned to this device ip_addresses = IPAddress.objects.filter(interface__device=device).select_related('interface', 'vrf')\ .order_by('address') + service_ports = ServicePort.objects.filter(ip_address__interface__device=device).order_by('ip_address', 'port') # Find any related devices for convenient linking in the UI related_devices = [] @@ -605,6 +606,7 @@ def device(request, pk): 'mgmt_interfaces': mgmt_interfaces, 'device_bays': device_bays, 'ip_addresses': ip_addresses, + 'service_ports': service_ports, 'secrets': secrets, 'related_devices': related_devices, 'show_graphs': show_graphs, @@ -1599,6 +1601,33 @@ def ipaddress_assign(request, pk): }) +@permission_required('ipam.add_ipaddress') +def serviceport_assign(request, pk): + device = get_object_or_404(Device, pk=pk) + + if request.method == 'POST': + form = forms.ServicePortForm(device, request.POST) + if form.is_valid(): + service_port = form.save(commit=False) + service_port.save() + messages.success(request, "Added new port {0} to IP Address {1}".format(service_port, + service_port.ip_address)) + + if '_addanother' in request.POST: + return redirect('dcim:serviceport_assign', pk=device.pk) + else: + return redirect('dcim:device', pk=device.pk) + + else: + form = forms.ServicePortForm(device) + + return render(request, 'dcim/serviceport_assign.html', { + 'device': device, + 'form': form, + 'cancel_url': reverse('dcim:device', kwargs={'pk': device.pk}), + }) + + # # Modules # diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 1a9e25db3..72e20f4d3 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -10,7 +10,7 @@ from utilities.forms import ( from .models import ( Aggregate, IPAddress, IPADDRESS_STATUS_CHOICES, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, VLAN, VLANGroup, - VLAN_STATUS_CHOICES, VRF, + VLAN_STATUS_CHOICES, VRF, ServicePort ) @@ -444,6 +444,24 @@ class IPAddressFilterForm(BootstrapMixin, CustomFieldFilterForm): status = forms.MultipleChoiceField(choices=ipaddress_status_choices, required=False) +# +# Service Port +# + +class ServicePortForm(forms.ModelForm, BootstrapMixin): + class Meta: + model = ServicePort + fields = ['ip_address', 'type', 'port', 'name', 'description'] + help_texts = { + 'port': '0-65535', + 'name': 'Service running on this port', + 'description': 'Service description' + } + labels = { + 'ip_address': "IP Address", + } + + # # VLAN groups # diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py index dc5fcc964..50aa6beb2 100644 --- a/netbox/ipam/urls.py +++ b/netbox/ipam/urls.py @@ -60,6 +60,9 @@ urlpatterns = [ url(r'^ip-addresses/(?P\d+)/remove/$', views.ipaddress_remove, name='ipaddress_remove'), url(r'^ip-addresses/(?P\d+)/delete/$', views.IPAddressDeleteView.as_view(), name='ipaddress_delete'), + # Service Ports + url(r'^service-ports/(?P\d+)/$', views.serviceport, name='serviceport'), + # VLAN groups url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'), url(r'^vlan-groups/add/$', views.VLANGroupEditView.as_view(), name='vlangroup_add'), diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 78bb1c148..9e399cc66 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -1,4 +1,3 @@ -from collections import OrderedDict from django_tables2 import RequestConfig import netaddr @@ -17,7 +16,8 @@ from utilities.views import ( ) from . import filters, forms, tables -from .models import Aggregate, IPAddress, PREFIX_STATUS_ACTIVE, PREFIX_STATUS_DEPRECATED, PREFIX_STATUS_RESERVED, Prefix, RIR, Role, VLAN, VLANGroup, VRF +from .models import (Aggregate, IPAddress, PREFIX_STATUS_ACTIVE, PREFIX_STATUS_DEPRECATED, PREFIX_STATUS_RESERVED, + Prefix, RIR, Role, VLAN, VLANGroup, VRF, ServicePort) def add_available_prefixes(parent, prefix_list): @@ -647,6 +647,16 @@ class IPAddressBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): # +# Service Ports +# + +def serviceport(request, pk): + service_port = get_object_or_404(ServicePort.objects.select_related('ip_address__interface__device'), pk=pk) + + return render(request, 'ipam/serviceport.html', { + 'service_port': service_port, + }) + # VLAN groups # diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index f4e7824b5..a9258fca6 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -220,6 +220,14 @@ None found {% endif %} + {% if perms.ipam.add_ipaddress %} + + {% endif %}
diff --git a/netbox/templates/dcim/serviceport_assign.html b/netbox/templates/dcim/serviceport_assign.html new file mode 100644 index 000000000..e5a0467fa --- /dev/null +++ b/netbox/templates/dcim/serviceport_assign.html @@ -0,0 +1,37 @@ +{% extends '_base.html' %} +{% load form_helpers %} + +{% block title %}Add a Service Port{% endblock %} + +{% block content %} +
+ {% csrf_token %} +
+
+ {% if form.non_field_errors %} +
+
Errors
+
+ {{ form.non_field_errors }} +
+
+ {% endif %} +
+
+ Add a Service Port +
+
+ {% render_form form %} +
+
+
+
+ + + Cancel +
+
+
+
+
+{% endblock %}