mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-28 11:26:26 -06:00
Add "Add ServicePort" functionality
This commit is contained in:
parent
df9557a328
commit
974d8419e6
@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db.models import Count, Q
|
from django.db.models import Count, Q
|
||||||
|
|
||||||
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
from extras.forms import CustomFieldForm, CustomFieldBulkEditForm, CustomFieldFilterForm
|
||||||
from ipam.models import IPAddress
|
from ipam.models import IPAddress, ServicePort
|
||||||
from tenancy.models import Tenant
|
from tenancy.models import Tenant
|
||||||
from utilities.forms import (
|
from utilities.forms import (
|
||||||
APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField, CSVDataField,
|
APISelect, add_blank_choice, BootstrapMixin, BulkEditForm, BulkImportForm, CommentField, CSVDataField,
|
||||||
@ -1265,6 +1265,28 @@ class IPAddressForm(BootstrapMixin, CustomFieldForm):
|
|||||||
self.fields['set_as_primary'].initial = True
|
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
|
# Modules
|
||||||
#
|
#
|
||||||
|
@ -103,6 +103,7 @@ urlpatterns = [
|
|||||||
url(r'^devices/(?P<pk>\d+)/inventory/$', views.device_inventory, name='device_inventory'),
|
url(r'^devices/(?P<pk>\d+)/inventory/$', views.device_inventory, name='device_inventory'),
|
||||||
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.device_lldp_neighbors, name='device_lldp_neighbors'),
|
url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.device_lldp_neighbors, name='device_lldp_neighbors'),
|
||||||
url(r'^devices/(?P<pk>\d+)/ip-addresses/assign/$', views.ipaddress_assign, name='ipaddress_assign'),
|
url(r'^devices/(?P<pk>\d+)/ip-addresses/assign/$', views.ipaddress_assign, name='ipaddress_assign'),
|
||||||
|
url(r'^devices/(?P<pk>\d+)/service-ports/assign/$', views.serviceport_assign, name='serviceport_assign'),
|
||||||
url(r'^devices/(?P<pk>\d+)/add-secret/$', secret_add, name='device_addsecret'),
|
url(r'^devices/(?P<pk>\d+)/add-secret/$', secret_add, name='device_addsecret'),
|
||||||
|
|
||||||
# Console ports
|
# Console ports
|
||||||
|
@ -15,7 +15,7 @@ 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 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 circuits.models import Circuit
|
||||||
from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
|
from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm
|
||||||
@ -576,6 +576,7 @@ def device(request, pk):
|
|||||||
# Find all IP addresses assigned to this device
|
# Find all IP addresses assigned to this device
|
||||||
ip_addresses = IPAddress.objects.filter(interface__device=device).select_related('interface', 'vrf')\
|
ip_addresses = IPAddress.objects.filter(interface__device=device).select_related('interface', 'vrf')\
|
||||||
.order_by('address')
|
.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
|
# Find any related devices for convenient linking in the UI
|
||||||
related_devices = []
|
related_devices = []
|
||||||
@ -605,6 +606,7 @@ def device(request, pk):
|
|||||||
'mgmt_interfaces': mgmt_interfaces,
|
'mgmt_interfaces': mgmt_interfaces,
|
||||||
'device_bays': device_bays,
|
'device_bays': device_bays,
|
||||||
'ip_addresses': ip_addresses,
|
'ip_addresses': ip_addresses,
|
||||||
|
'service_ports': service_ports,
|
||||||
'secrets': secrets,
|
'secrets': secrets,
|
||||||
'related_devices': related_devices,
|
'related_devices': related_devices,
|
||||||
'show_graphs': show_graphs,
|
'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
|
# Modules
|
||||||
#
|
#
|
||||||
|
@ -10,7 +10,7 @@ from utilities.forms import (
|
|||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Aggregate, IPAddress, IPADDRESS_STATUS_CHOICES, Prefix, PREFIX_STATUS_CHOICES, RIR, Role, VLAN, VLANGroup,
|
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)
|
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
|
# VLAN groups
|
||||||
#
|
#
|
||||||
|
@ -60,6 +60,9 @@ urlpatterns = [
|
|||||||
url(r'^ip-addresses/(?P<pk>\d+)/remove/$', views.ipaddress_remove, name='ipaddress_remove'),
|
url(r'^ip-addresses/(?P<pk>\d+)/remove/$', views.ipaddress_remove, name='ipaddress_remove'),
|
||||||
url(r'^ip-addresses/(?P<pk>\d+)/delete/$', views.IPAddressDeleteView.as_view(), name='ipaddress_delete'),
|
url(r'^ip-addresses/(?P<pk>\d+)/delete/$', views.IPAddressDeleteView.as_view(), name='ipaddress_delete'),
|
||||||
|
|
||||||
|
# Service Ports
|
||||||
|
url(r'^service-ports/(?P<pk>\d+)/$', views.serviceport, name='serviceport'),
|
||||||
|
|
||||||
# VLAN groups
|
# VLAN groups
|
||||||
url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'),
|
url(r'^vlan-groups/$', views.VLANGroupListView.as_view(), name='vlangroup_list'),
|
||||||
url(r'^vlan-groups/add/$', views.VLANGroupEditView.as_view(), name='vlangroup_add'),
|
url(r'^vlan-groups/add/$', views.VLANGroupEditView.as_view(), name='vlangroup_add'),
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
from collections import OrderedDict
|
|
||||||
from django_tables2 import RequestConfig
|
from django_tables2 import RequestConfig
|
||||||
import netaddr
|
import netaddr
|
||||||
|
|
||||||
@ -17,7 +16,8 @@ from utilities.views import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from . import filters, forms, tables
|
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):
|
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
|
# VLAN groups
|
||||||
#
|
#
|
||||||
|
|
||||||
|
@ -220,6 +220,14 @@
|
|||||||
None found
|
None found
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if perms.ipam.add_ipaddress %}
|
||||||
|
<div class="panel-footer text-right">
|
||||||
|
<a href="{% url 'dcim:serviceport_assign' pk=device.pk %}" class="btn btn-xs btn-primary">
|
||||||
|
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||||
|
Assign port
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
|
37
netbox/templates/dcim/serviceport_assign.html
Normal file
37
netbox/templates/dcim/serviceport_assign.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends '_base.html' %}
|
||||||
|
{% load form_helpers %}
|
||||||
|
|
||||||
|
{% block title %}Add a Service Port{% 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">
|
||||||
|
Add a Service Port
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{% render_form form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-9 col-md-offset-3">
|
||||||
|
<button type="submit" name="_create" class="btn btn-primary">Create</button>
|
||||||
|
<button type="submit" name="_addanother" class="btn btn-primary">Create and Add More</button>
|
||||||
|
<a href="{{ cancel_url }}" class="btn btn-default">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue
Block a user