Added additional field connection_name for interface connection

Added additional field connection_name for interface connection to track e.g.
cable numbers.
Therefore it was necessary to change the edit the template as well.
This commit is contained in:
Walter Werther 2017-12-26 21:11:34 +01:00
parent ec0cb7a8bc
commit e44d0c3ea5
7 changed files with 123 additions and 17 deletions

View File

@ -1692,10 +1692,67 @@ class InterfaceBulkDisconnectForm(ConfirmationForm):
#
class InterfaceConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm):
interface_a = forms.ChoiceField(
choices=[],
site_a = forms.ModelChoiceField(
queryset=Site.objects.all(),
label='Site',
required=False,
widget=forms.Select(
attrs={'filter-for': 'rack_a'}
)
)
rack_a = ChainedModelChoiceField(
queryset=Rack.objects.all(),
chains=(
('site', 'site_a'),
),
label='Rack',
required=False,
widget=APISelect(
api_url='/api/dcim/racks/?site_id={{site_a}}',
attrs={'filter-for': 'device_a', 'nullable': 'true'}
)
)
device_a = ChainedModelChoiceField(
queryset=Device.objects.all(),
chains=(
('site', 'site_a'),
('rack', 'rack_a'),
),
label='Device',
required=False,
widget=APISelect(
api_url='/api/dcim/devices/?site_id={{site_a}}&rack_id={{rack_a}}',
display_field='display_name',
attrs={'filter-for': 'interface_a'}
)
)
livesearch_a = forms.CharField(
required=False,
label='Device',
widget=Livesearch(
query_key='q',
query_url='dcim-api:device-list',
field_to_update='device_a'
)
)
#interface_a = forms.ChoiceField(
# choices=[],
# widget=SelectWithDisabled,
# label='Interface'
#)
interface_a = ChainedModelChoiceField(
queryset=Interface.objects.connectable().select_related(
'circuit_termination', 'connected_as_a', 'connected_as_b'
),
chains=(
('device', 'device_a'),
),
label='Interface',
widget=SelectWithDisabled,
label='Interface'
#widget=APISelect(
# api_url='/api/dcim/interfaces/?device_id={{device_a}}&type=physical',
# disabled_indicator='is_connected'
#)
)
site_b = forms.ModelChoiceField(
queryset=Site.objects.all(),
@ -1756,20 +1813,34 @@ class InterfaceConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelFor
class Meta:
model = InterfaceConnection
fields = ['interface_a', 'site_b', 'rack_b', 'device_b', 'interface_b', 'livesearch', 'connection_status']
fields = ['site_a','rack_a','device_a','interface_a', 'livesearch_a','site_b', 'rack_b', 'device_b', 'interface_b', 'livesearch', 'connection_status','connection_name']
def __init__(self, device_a, *args, **kwargs):
def __init__(self, *args, **kwargs):
super(InterfaceConnectionForm, self).__init__(*args, **kwargs)
#if self.instance.pk:
#else:
if self.initial.get('device_a'):
# Initialize interface A choices
device_a_interfaces = Interface.objects.connectable().order_naturally().filter(device=device_a).select_related(
device_a_interfaces = Interface.objects.connectable().order_naturally().filter(device=self.initial['device_a']).select_related(
'circuit_termination', 'connected_as_a', 'connected_as_b'
)
self.fields['interface_a'].choices = [
(iface.id, {'label': iface.name, 'disabled': iface.is_connected}) for iface in device_a_interfaces
]
# Mark connected interfaces as disabled
if self.data.get('device_a'):
self.fields['interface_a'].choices = [
(iface.id, {'label': iface.name, 'disabled': iface.is_connected}) for iface in self.fields['interface_a'].queryset
]
# Mark connected interfaces as disabled
if self.data.get('device_b'):
self.fields['interface_b'].choices = [
@ -1800,10 +1871,14 @@ class InterfaceConnectionCSVForm(forms.ModelForm):
choices=CONNECTION_STATUS_CHOICES,
help_text='Connection status'
)
connection_name = forms.CharField(
help_text='Name of this connection (e.g. cable-number)',
required = False
)
class Meta:
model = InterfaceConnection
fields = ['device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status']
fields = ['device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status','connection_name']
def clean_interface_a(self):

View File

@ -1370,8 +1370,9 @@ class InterfaceConnection(models.Model):
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_name = models.CharField(max_length = 64,blank = True)
csv_headers = ['device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status']
csv_headers = ['device_a', 'interface_a', 'device_b', 'interface_b', 'connection_status','connection_name']
def clean(self):
try:
@ -1390,6 +1391,7 @@ class InterfaceConnection(models.Model):
self.interface_b.device.identifier,
self.interface_b.name,
self.get_connection_status_display(),
self.connection_name,
])

View File

@ -519,7 +519,8 @@ class InterfaceConnectionTable(BaseTable):
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')
connection_name = tables.Column(verbose_name='Connection Name')
class Meta(BaseTable.Meta):
model = Interface
fields = ('device_a', 'interface_a', 'device_b', 'interface_b')
fields = ('device_a', 'interface_a', 'device_b', 'interface_b','connection_name')

View File

@ -182,6 +182,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
url(r'^devices/(?P<pk>\d+)/interface-connections/add/$', views.interfaceconnection_add, name='interfaceconnection_add'),
url(r'^interface-connections/(?P<pk>\d+)/delete/$', views.interfaceconnection_delete, name='interfaceconnection_delete'),
url(r'^interface-connections/(?P<pk>\d+)/edit/$', views.InterfaceConnectionEditView.as_view(), name='interfaceconnection_edit'),
url(r'^interfaces/(?P<pk>\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'),
url(r'^interfaces/(?P<pk>\d+)/delete/$', views.InterfaceDeleteView.as_view(), name='interface_delete'),

View File

@ -1682,7 +1682,7 @@ def interfaceconnection_add(request, pk):
device = get_object_or_404(Device, pk=pk)
if request.method == 'POST':
form = forms.InterfaceConnectionForm(device, request.POST)
form = forms.InterfaceConnectionForm( request.POST)
if form.is_valid():
interfaceconnection = form.save()
@ -1709,12 +1709,14 @@ def interfaceconnection_add(request, pk):
return redirect('dcim:device', pk=device.pk)
else:
form = forms.InterfaceConnectionForm(device, initial={
form = forms.InterfaceConnectionForm(initial={
'device_a': pk,
'interface_a': request.GET.get('interface_a'),
'site_b': request.GET.get('site_b'),
'rack_b': request.GET.get('rack_b'),
'device_b': request.GET.get('device_b'),
'interface_b': request.GET.get('interface_b'),
'connection_name': request.GET.get('connection_name'),
})
return render(request, 'dcim/interfaceconnection_edit.html', {
@ -1768,6 +1770,21 @@ def interfaceconnection_delete(request, pk):
})
class InterfaceConnectionEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'dcim.edit_interfaceconnection'
model = InterfaceConnection
#parent_field = 'id'
model_form = forms.InterfaceConnectionForm
template_name = 'dcim/interfaceconnection_edit.html'
#template_name = 'dcim/device_edit.html'
#default_return_url = 'dcim:device_list'
#def alter_obj(self, obj, request, url_args, url_kwargs):
# if 'device' in url_kwargs:
# obj.device = get_object_or_404(InterfaceConnection, pk=url_kwargs['device'])
# return obj
class InterfaceConnectionsBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'dcim.change_interface'
model_form = forms.InterfaceConnectionCSVForm

View File

@ -48,6 +48,7 @@
</td>
<td>
<span title="{{ connected_iface.get_form_factor_display }}">{{ connected_iface }}</span>
{% if iface.connection.connection_name %}<br /> <small class="text-muted">(via {{ iface.connection.connection_name }})</small>{% endif %}
</td>
{% endwith %}
{% elif iface.circuit_termination %}
@ -98,6 +99,9 @@
<i class="fa fa-plug" aria-hidden="true"></i>
</a>
{% endif %}
<!-- <a href="{% url 'dcim:interfaceconnection_edit' pk=iface.connection.pk %}?interface_a={{ iface.pk }}" class="btn btn-info btn-xs" title="Edit Interfaceconnection">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a> -->
<a href="{% url 'dcim:interfaceconnection_delete' pk=iface.connection.pk %}?device={{ device.pk }}" class="btn btn-danger btn-xs" title="Disconnect">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
</a>

View File

@ -82,6 +82,12 @@
{% render_field form.connection_status %}
</div>
</div>
<div class="row">
<!-- connection name -->
<div class="col-md-4 col-md-offset-4">
{% render_field form.connection_name %}
</div>
</div>
<div class="text-center">
<div class="form-group">
<button type="submit" name="_create" class="btn btn-primary">Connect</button>