Provide individual views for each type of cable connection

This commit is contained in:
Jeremy Stretch 2019-04-09 16:49:04 -04:00
parent ef867e789d
commit c1127148e2
12 changed files with 198 additions and 86 deletions

View File

@ -43,7 +43,7 @@ urlpatterns = [
url(r'^circuits/(?P<circuit>\d+)/terminations/add/$', views.CircuitTerminationCreateView.as_view(), name='circuittermination_add'), url(r'^circuits/(?P<circuit>\d+)/terminations/add/$', views.CircuitTerminationCreateView.as_view(), name='circuittermination_add'),
url(r'^circuit-terminations/(?P<pk>\d+)/edit/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'), url(r'^circuit-terminations/(?P<pk>\d+)/edit/$', views.CircuitTerminationEditView.as_view(), name='circuittermination_edit'),
url(r'^circuit-terminations/(?P<pk>\d+)/delete/$', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'), url(r'^circuit-terminations/(?P<pk>\d+)/delete/$', views.CircuitTerminationDeleteView.as_view(), name='circuittermination_delete'),
url(r'^circuit-terminations/(?P<termination_a_id>\d+)/connect/$', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}), url(r'^circuit-terminations/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', CableCreateView.as_view(), name='circuittermination_connect', kwargs={'termination_a_type': CircuitTermination}),
url(r'^circuit-terminations/(?P<pk>\d+)/trace/$', CableTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}), url(r'^circuit-terminations/(?P<pk>\d+)/trace/$', CableTraceView.as_view(), name='circuittermination_trace', kwargs={'model': CircuitTermination}),
] ]

View File

@ -2522,6 +2522,9 @@ class RearPortBulkDisconnectForm(ConfirmationForm):
# #
class ConnectCableToDeviceForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm): class ConnectCableToDeviceForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm):
"""
Base form for connecting a Cable to a Device component
"""
termination_b_site = forms.ModelChoiceField( termination_b_site = forms.ModelChoiceField(
queryset=Site.objects.all(), queryset=Site.objects.all(),
label='Site', label='Site',
@ -2567,42 +2570,89 @@ class ConnectCableToDeviceForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelFo
} }
) )
) )
termination_b_type = forms.ModelChoiceField(
queryset=ContentType.objects.all(),
label='Type',
widget=ContentTypeSelect()
)
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/{{termination_b_type}}s/',
disabled_indicator='cable',
conditional_query_params={
'termination_b_type__interface': 'type=physical',
}
)
)
class Meta: class Meta:
model = Cable model = Cable
fields = [ fields = [
'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_type', 'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_id', 'type', 'status',
'termination_b_id', 'type', 'status', 'label', 'color', 'length', 'length_unit', 'label', 'color', 'length', 'length_unit',
] ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Define available types for endpoint B based on the type of endpoint A class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
termination_a_type = self.instance.termination_a._meta.model_name termination_b_id = forms.IntegerField(
self.fields['termination_b_type'].queryset = ContentType.objects.filter( label='Name',
model__in=COMPATIBLE_TERMINATION_TYPES.get(termination_a_type) widget=APISelect(
).exclude( api_url='/api/dcim/console-ports/',
model='circuittermination' disabled_indicator='cable',
) )
)
class ConnectCableToCircuitForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm): class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/console-server-ports/',
disabled_indicator='cable',
)
)
class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/power-ports/',
disabled_indicator='cable',
)
)
class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/power-outlets/',
disabled_indicator='cable',
)
)
class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/interfaces/',
disabled_indicator='cable',
additional_query_params={
'type': 'physical',
}
)
)
class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/front-ports/',
disabled_indicator='cable',
)
)
class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
termination_b_id = forms.IntegerField(
label='Name',
widget=APISelect(
api_url='/api/dcim/rear-ports/',
disabled_indicator='cable',
)
)
class ConnectCableToCircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm):
termination_b_provider = forms.ModelChoiceField( termination_b_provider = forms.ModelChoiceField(
queryset=Provider.objects.all(), queryset=Provider.objects.all(),
label='Provider', label='Provider',
@ -2613,6 +2663,17 @@ class ConnectCableToCircuitForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelF
} }
) )
) )
termination_b_site = forms.ModelChoiceField(
queryset=Site.objects.all(),
label='Site',
required=False,
widget=APISelect(
api_url='/api/dcim/sites/',
filter_for={
'termination_b_circuit': 'site_id',
}
)
)
termination_b_circuit = ChainedModelChoiceField( termination_b_circuit = ChainedModelChoiceField(
queryset=Circuit.objects.all(), queryset=Circuit.objects.all(),
chains=( chains=(
@ -2628,18 +2689,19 @@ class ConnectCableToCircuitForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelF
) )
) )
termination_b_id = forms.IntegerField( termination_b_id = forms.IntegerField(
label='Termination', label='Side',
widget=APISelect( widget=APISelect(
api_url='/api/circuits/circuit-terminations/', api_url='/api/circuits/circuit-terminations/',
disabled_indicator='cable' disabled_indicator='cable',
display_field='term_side'
) )
) )
class Meta: class Meta:
model = Cable model = Cable
fields = [ fields = [
'termination_b_provider', 'termination_b_circuit', 'termination_b_id', 'type', 'status', 'label', 'color', 'termination_b_provider', 'termination_b_site', 'termination_b_circuit', 'termination_b_id', 'type',
'length', 'length_unit', 'status', 'label', 'color', 'length', 'length_unit',
] ]
@ -2686,7 +2748,7 @@ class ConnectCableToPowerFeedForm(BootstrapMixin, ChainedFieldsMixin, forms.Mode
) )
) )
termination_b_id = forms.IntegerField( termination_b_id = forms.IntegerField(
label='Power Feed', label='Name',
widget=APISelect( widget=APISelect(
api_url='/api/dcim/power-feeds/', api_url='/api/dcim/power-feeds/',
) )

View File

@ -162,7 +162,7 @@ urlpatterns = [
url(r'^devices/console-ports/add/$', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'), url(r'^devices/console-ports/add/$', views.DeviceBulkAddConsolePortView.as_view(), name='device_bulk_add_consoleport'),
url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortCreateView.as_view(), name='consoleport_add'), url(r'^devices/(?P<pk>\d+)/console-ports/add/$', views.ConsolePortCreateView.as_view(), name='consoleport_add'),
url(r'^devices/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'), url(r'^devices/(?P<pk>\d+)/console-ports/delete/$', views.ConsolePortBulkDeleteView.as_view(), name='consoleport_bulk_delete'),
url(r'^console-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='consoleport_connect', kwargs={'termination_a_type': ConsolePort}), url(r'^console-ports/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='consoleport_connect', kwargs={'termination_a_type': ConsolePort}),
url(r'^console-ports/(?P<pk>\d+)/edit/$', views.ConsolePortEditView.as_view(), name='consoleport_edit'), url(r'^console-ports/(?P<pk>\d+)/edit/$', views.ConsolePortEditView.as_view(), name='consoleport_edit'),
url(r'^console-ports/(?P<pk>\d+)/delete/$', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'), url(r'^console-ports/(?P<pk>\d+)/delete/$', views.ConsolePortDeleteView.as_view(), name='consoleport_delete'),
url(r'^console-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}), url(r'^console-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleport_trace', kwargs={'model': ConsolePort}),
@ -171,7 +171,7 @@ urlpatterns = [
url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'), url(r'^devices/console-server-ports/add/$', views.DeviceBulkAddConsoleServerPortView.as_view(), name='device_bulk_add_consoleserverport'),
url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'), url(r'^devices/(?P<pk>\d+)/console-server-ports/add/$', views.ConsoleServerPortCreateView.as_view(), name='consoleserverport_add'),
url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'), url(r'^devices/(?P<pk>\d+)/console-server-ports/delete/$', views.ConsoleServerPortBulkDeleteView.as_view(), name='consoleserverport_bulk_delete'),
url(r'^console-server-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}), url(r'^console-server-ports/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='consoleserverport_connect', kwargs={'termination_a_type': ConsoleServerPort}),
url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'), url(r'^console-server-ports/(?P<pk>\d+)/edit/$', views.ConsoleServerPortEditView.as_view(), name='consoleserverport_edit'),
url(r'^console-server-ports/(?P<pk>\d+)/delete/$', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'), url(r'^console-server-ports/(?P<pk>\d+)/delete/$', views.ConsoleServerPortDeleteView.as_view(), name='consoleserverport_delete'),
url(r'^console-server-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}), url(r'^console-server-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='consoleserverport_trace', kwargs={'model': ConsoleServerPort}),
@ -182,7 +182,7 @@ urlpatterns = [
url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'), url(r'^devices/power-ports/add/$', views.DeviceBulkAddPowerPortView.as_view(), name='device_bulk_add_powerport'),
url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.PowerPortCreateView.as_view(), name='powerport_add'), url(r'^devices/(?P<pk>\d+)/power-ports/add/$', views.PowerPortCreateView.as_view(), name='powerport_add'),
url(r'^devices/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'), url(r'^devices/(?P<pk>\d+)/power-ports/delete/$', views.PowerPortBulkDeleteView.as_view(), name='powerport_bulk_delete'),
url(r'^power-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='powerport_connect', kwargs={'termination_a_type': PowerPort}), url(r'^power-ports/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='powerport_connect', kwargs={'termination_a_type': PowerPort}),
url(r'^power-ports/(?P<pk>\d+)/edit/$', views.PowerPortEditView.as_view(), name='powerport_edit'), url(r'^power-ports/(?P<pk>\d+)/edit/$', views.PowerPortEditView.as_view(), name='powerport_edit'),
url(r'^power-ports/(?P<pk>\d+)/delete/$', views.PowerPortDeleteView.as_view(), name='powerport_delete'), url(r'^power-ports/(?P<pk>\d+)/delete/$', views.PowerPortDeleteView.as_view(), name='powerport_delete'),
url(r'^power-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}), url(r'^power-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='powerport_trace', kwargs={'model': PowerPort}),
@ -191,7 +191,7 @@ urlpatterns = [
url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'), url(r'^devices/power-outlets/add/$', views.DeviceBulkAddPowerOutletView.as_view(), name='device_bulk_add_poweroutlet'),
url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'), url(r'^devices/(?P<pk>\d+)/power-outlets/add/$', views.PowerOutletCreateView.as_view(), name='poweroutlet_add'),
url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'), url(r'^devices/(?P<pk>\d+)/power-outlets/delete/$', views.PowerOutletBulkDeleteView.as_view(), name='poweroutlet_bulk_delete'),
url(r'^power-outlets/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}), url(r'^power-outlets/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='poweroutlet_connect', kwargs={'termination_a_type': PowerOutlet}),
url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'), url(r'^power-outlets/(?P<pk>\d+)/edit/$', views.PowerOutletEditView.as_view(), name='poweroutlet_edit'),
url(r'^power-outlets/(?P<pk>\d+)/delete/$', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'), url(r'^power-outlets/(?P<pk>\d+)/delete/$', views.PowerOutletDeleteView.as_view(), name='poweroutlet_delete'),
url(r'^power-outlets/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}), url(r'^power-outlets/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='poweroutlet_trace', kwargs={'model': PowerOutlet}),
@ -203,7 +203,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'), url(r'^devices/(?P<pk>\d+)/interfaces/add/$', views.InterfaceCreateView.as_view(), name='interface_add'),
url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'), url(r'^devices/(?P<pk>\d+)/interfaces/edit/$', views.InterfaceBulkEditView.as_view(), name='interface_bulk_edit'),
url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'), url(r'^devices/(?P<pk>\d+)/interfaces/delete/$', views.InterfaceBulkDeleteView.as_view(), name='interface_bulk_delete'),
url(r'^interfaces/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}), url(r'^interfaces/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='interface_connect', kwargs={'termination_a_type': Interface}),
url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceView.as_view(), name='interface'), url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceView.as_view(), name='interface'),
url(r'^interfaces/(?P<pk>\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'), url(r'^interfaces/(?P<pk>\d+)/edit/$', views.InterfaceEditView.as_view(), name='interface_edit'),
url(r'^interfaces/(?P<pk>\d+)/assign-vlans/$', views.InterfaceAssignVLANsView.as_view(), name='interface_assign_vlans'), url(r'^interfaces/(?P<pk>\d+)/assign-vlans/$', views.InterfaceAssignVLANsView.as_view(), name='interface_assign_vlans'),
@ -218,7 +218,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/front-ports/add/$', views.FrontPortCreateView.as_view(), name='frontport_add'), url(r'^devices/(?P<pk>\d+)/front-ports/add/$', views.FrontPortCreateView.as_view(), name='frontport_add'),
url(r'^devices/(?P<pk>\d+)/front-ports/edit/$', views.FrontPortBulkEditView.as_view(), name='frontport_bulk_edit'), url(r'^devices/(?P<pk>\d+)/front-ports/edit/$', views.FrontPortBulkEditView.as_view(), name='frontport_bulk_edit'),
url(r'^devices/(?P<pk>\d+)/front-ports/delete/$', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'), url(r'^devices/(?P<pk>\d+)/front-ports/delete/$', views.FrontPortBulkDeleteView.as_view(), name='frontport_bulk_delete'),
url(r'^front-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}), url(r'^front-ports/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='frontport_connect', kwargs={'termination_a_type': FrontPort}),
url(r'^front-ports/(?P<pk>\d+)/edit/$', views.FrontPortEditView.as_view(), name='frontport_edit'), url(r'^front-ports/(?P<pk>\d+)/edit/$', views.FrontPortEditView.as_view(), name='frontport_edit'),
url(r'^front-ports/(?P<pk>\d+)/delete/$', views.FrontPortDeleteView.as_view(), name='frontport_delete'), url(r'^front-ports/(?P<pk>\d+)/delete/$', views.FrontPortDeleteView.as_view(), name='frontport_delete'),
url(r'^front-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}), url(r'^front-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='frontport_trace', kwargs={'model': FrontPort}),
@ -230,7 +230,7 @@ urlpatterns = [
url(r'^devices/(?P<pk>\d+)/rear-ports/add/$', views.RearPortCreateView.as_view(), name='rearport_add'), url(r'^devices/(?P<pk>\d+)/rear-ports/add/$', views.RearPortCreateView.as_view(), name='rearport_add'),
url(r'^devices/(?P<pk>\d+)/rear-ports/edit/$', views.RearPortBulkEditView.as_view(), name='rearport_bulk_edit'), url(r'^devices/(?P<pk>\d+)/rear-ports/edit/$', views.RearPortBulkEditView.as_view(), name='rearport_bulk_edit'),
url(r'^devices/(?P<pk>\d+)/rear-ports/delete/$', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'), url(r'^devices/(?P<pk>\d+)/rear-ports/delete/$', views.RearPortBulkDeleteView.as_view(), name='rearport_bulk_delete'),
url(r'^rear-ports/(?P<termination_a_id>\d+)/connect/$', views.CableCreateView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}), url(r'^rear-ports/(?P<termination_a_id>\d+)/connect/(?P<termination_b_type>[\w-]+)/$', views.CableCreateView.as_view(), name='rearport_connect', kwargs={'termination_a_type': RearPort}),
url(r'^rear-ports/(?P<pk>\d+)/edit/$', views.RearPortEditView.as_view(), name='rearport_edit'), url(r'^rear-ports/(?P<pk>\d+)/edit/$', views.RearPortEditView.as_view(), name='rearport_edit'),
url(r'^rear-ports/(?P<pk>\d+)/delete/$', views.RearPortDeleteView.as_view(), name='rearport_delete'), url(r'^rear-ports/(?P<pk>\d+)/delete/$', views.RearPortDeleteView.as_view(), name='rearport_delete'),
url(r'^rear-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}), url(r'^rear-ports/(?P<pk>\d+)/trace/$', views.CableTraceView.as_view(), name='rearport_trace', kwargs={'model': RearPort}),

View File

@ -15,7 +15,7 @@ from django.utils.http import is_safe_url
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.views.generic import View from django.views.generic import View
from circuits.models import Circuit, CircuitTermination 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 extras.views import ObjectConfigContextView from extras.views import ObjectConfigContextView
from ipam.models import Prefix, VLAN from ipam.models import Prefix, VLAN
@ -1679,27 +1679,28 @@ class CableCreateView(PermissionRequiredMixin, GetReturnURLMixin, View):
permission_required = 'dcim.add_cable' permission_required = 'dcim.add_cable'
template_name = 'dcim/cable_connect.html' template_name = 'dcim/cable_connect.html'
def _get_form_class(self):
if self.termination_b_type == 'circuit':
return forms.ConnectCableToCircuitForm
if self.termination_b_type == 'powerfeed':
return forms.ConnectCableToPowerFeedForm
return forms.ConnectCableToDeviceForm
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
# Retrieve endpoint A based on the given type and PK
termination_a_type = kwargs.get('termination_a_type') termination_a_type = kwargs.get('termination_a_type')
termination_a_id = kwargs.get('termination_a_id') termination_a_id = kwargs.get('termination_a_id')
self.obj = Cable(
termination_a=termination_a_type.objects.get(pk=termination_a_id)
)
self.termination_b_type = request.GET.get('type') termination_b_type_name = kwargs.get('termination_b_type')
if self.termination_b_type == 'circuit': self.termination_b_type = ContentType.objects.get(model=termination_b_type_name.replace('-', ''))
self.obj.termination_b_type = ContentType.objects.get_for_model(CircuitTermination)
elif self.termination_b_type == 'powerfeed': self.obj = Cable(
self.obj.termination_b_type = ContentType.objects.get_for_model(PowerFeed) termination_a=termination_a_type.objects.get(pk=termination_a_id),
termination_b_type=self.termination_b_type
)
self.form_class = {
'console-port': forms.ConnectCableToConsolePortForm,
'console-server-port': forms.ConnectCableToConsoleServerPortForm,
'power-port': forms.ConnectCableToPowerPortForm,
'power-outlet': forms.ConnectCableToPowerOutletForm,
'interface': forms.ConnectCableToInterfaceForm,
'front-port': forms.ConnectCableToFrontPortForm,
'power-feed': forms.ConnectCableToPowerFeedForm,
'circuit-termination': forms.ConnectCableToCircuitTerminationForm,
}[termination_b_type_name]
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
@ -1708,18 +1709,19 @@ class CableCreateView(PermissionRequiredMixin, GetReturnURLMixin, View):
# Parse initial data manually to avoid setting field values as lists # Parse initial data manually to avoid setting field values as lists
initial_data = {k: request.GET[k] for k in request.GET} initial_data = {k: request.GET[k] for k in request.GET}
form = self._get_form_class()(instance=self.obj, initial=initial_data) form = self.form_class(instance=self.obj, initial=initial_data)
return render(request, self.template_name, { return render(request, self.template_name, {
'obj': self.obj, 'obj': self.obj,
'obj_type': Cable._meta.verbose_name, 'obj_type': Cable._meta.verbose_name,
'termination_b_type': self.termination_b_type.name,
'form': form, 'form': form,
'return_url': self.get_return_url(request, self.obj), 'return_url': self.get_return_url(request, self.obj),
}) })
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self._get_form_class()(request.POST, request.FILES, instance=self.obj) form = self.form_class(request.POST, request.FILES, instance=self.obj)
if form.is_valid(): if form.is_valid():
obj = form.save() obj = form.save()
@ -1742,6 +1744,7 @@ class CableCreateView(PermissionRequiredMixin, GetReturnURLMixin, View):
return render(request, self.template_name, { return render(request, self.template_name, {
'obj': self.obj, 'obj': self.obj,
'obj_type': Cable._meta.verbose_name, 'obj_type': Cable._meta.verbose_name,
'termination_b_type': self.termination_b_type.name,
'form': form, 'form': form,
'return_url': self.get_return_url(request, self.obj), 'return_url': self.get_return_url(request, self.obj),
}) })

View File

@ -22,7 +22,7 @@
</div> </div>
{% endif %} {% endif %}
{% with termination_a=form.instance.termination_a %} {% with termination_a=form.instance.termination_a %}
<h3>{% block title %}Connect {{ termination_a.device }} {{ termination_a }}{% endblock %}</h3> <h3>{% block title %}Connect {{ termination_a.device }} {{ termination_a }} to {{ termination_b_type|bettertitle }}{% endblock %}</h3>
<div class="row"> <div class="row">
<div class="col-md-5"> <div class="col-md-5">
<div class="panel panel-default"> <div class="panel panel-default">
@ -101,7 +101,16 @@
<strong>B Side</strong> <strong>B Side</strong>
</div> </div>
<div class="panel-body"> <div class="panel-body">
{# TODO: Clean this up #} {% if tabs %}
<ul class="nav nav-tabs">
{% for url, link in tabs %}
<li role="presentation"><a href="{{ url }}">{{ link }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% if 'termination_b_provider' in form.fields %}
{% render_field form.termination_b_provider %}
{% endif %}
{% if 'termination_b_site' in form.fields %} {% if 'termination_b_site' in form.fields %}
{% render_field form.termination_b_site %} {% render_field form.termination_b_site %}
{% endif %} {% endif %}
@ -117,18 +126,18 @@
{% if 'termination_b_type' in form.fields %} {% if 'termination_b_type' in form.fields %}
{% render_field form.termination_b_type %} {% render_field form.termination_b_type %}
{% endif %} {% endif %}
{% if 'termination_b_provider' in form.fields %} {% if 'termination_b_powerpanel' in form.fields %}
{% render_field form.termination_b_provider %} {% render_field form.termination_b_powerpanel %}
{% endif %} {% endif %}
{% if 'termination_b_circuit' in form.fields %} {% if 'termination_b_circuit' in form.fields %}
{% render_field form.termination_b_circuit %} {% render_field form.termination_b_circuit %}
{% endif %} {% endif %}
{% if 'termination_b_powerpanel' in form.fields %} <div class="form-group">
{% render_field form.termination_b_powerpanel %} <label class="col-md-3 control-label required">Type</label>
{% endif %} <div class="col-md-9">
{% if 'termination_b_powerfeed' in form.fields %} <p class="form-control-static">{{ termination_b_type|capfirst }}</p>
{% render_field form.termination_b_powerfeed %} </div>
{% endif %} </div>
{% render_field form.termination_b_id %} {% render_field form.termination_b_id %}
</div> </div>
</div> </div>

View File

@ -38,9 +38,16 @@
{% if cp.cable %} {% if cp.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=cp.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=cp.cable %}
{% elif perms.dcim.add_cable %} {% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs"> <span class="dropdown">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</a> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='console-server-port' %}?return_url={{ device.get_absolute_url }}">Console Server Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleport_connect' termination_a_id=cp.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %} {% endif %}
{% if perms.dcim.change_consoleport %} {% if perms.dcim.change_consoleport %}
<a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" title="Edit port" class="btn btn-info btn-xs"> <a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" title="Edit port" class="btn btn-info btn-xs">

View File

@ -47,9 +47,16 @@
{% if csp.cable %} {% if csp.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=csp.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=csp.cable %}
{% elif perms.dcim.add_cable %} {% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs"> <span class="dropdown">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</a> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='console-port' %}?return_url={{ device.get_absolute_url }}">Console Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:consoleserverport_connect' termination_a_id=csp.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
</ul>
</span>
{% endif %} {% endif %}
{% if perms.dcim.change_consoleserverport %} {% if perms.dcim.change_consoleserverport %}
<a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" title="Edit port" class="btn btn-info btn-xs"> <a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" title="Edit port" class="btn btn-info btn-xs">

View File

@ -58,9 +58,17 @@
{% if frontport.cable %} {% if frontport.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=frontport.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=frontport.cable %}
{% elif perms.dcim.add_cable %} {% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-success btn-xs" title="Connect"> <span class="dropdown">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</a> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:frontport_connect' termination_a_id=frontport.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %} {% endif %}
{% if perms.dcim.change_frontport %} {% if perms.dcim.change_frontport %}
<a href="{% url 'dcim:frontport_edit' pk=frontport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs"> <a href="{% url 'dcim:frontport_edit' pk=frontport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">

View File

@ -151,9 +151,17 @@
{% if iface.cable %} {% if iface.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=iface.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=iface.cable %}
{% elif iface.is_connectable and perms.dcim.add_cable %} {% elif iface.is_connectable and perms.dcim.add_cable %}
<a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-success btn-xs" title="Connect"> <span class="dropdown">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</a> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:interface_connect' termination_a_id=iface.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %} {% endif %}
<a href="{% if iface.device_id %}{% url 'dcim:interface_edit' pk=iface.pk %}{% else %}{% url 'virtualization:interface_edit' pk=iface.pk %}{% endif %}?return_url={{ device.get_absolute_url }}" class="btn btn-info btn-xs" title="Edit interface"> <a href="{% if iface.device_id %}{% url 'dcim:interface_edit' pk=iface.pk %}{% else %}{% url 'virtualization:interface_edit' pk=iface.pk %}{% endif %}?return_url={{ device.get_absolute_url }}" class="btn btn-info btn-xs" title="Edit interface">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i> <i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>

View File

@ -47,7 +47,7 @@
{% if po.cable %} {% if po.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=po.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=po.cable %}
{% elif perms.dcim.add_cable %} {% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:poweroutlet_connect' termination_a_id=po.pk %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs"> <a href="{% url 'dcim:poweroutlet_connect' termination_a_id=po.pk termination_b_type='power-outlet' %}?return_url={{ device.get_absolute_url }}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a> </a>
{% endif %} {% endif %}

View File

@ -47,8 +47,8 @@
<span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button> </button>
<ul class="dropdown-menu dropdown-menu-right"> <ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk %}?return_url={{ device.get_absolute_url }}">Power Outlet</a></li> <li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk termination_b_type='power-outlet' %}?return_url={{ device.get_absolute_url }}">Power Outlet</a></li>
<li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk %}?type=powerfeed&return_url={{ device.get_absolute_url }}">Power Feed</a></li> <li><a href="{% url 'dcim:powerport_connect' termination_a_id=pp.pk termination_b_type='power-feed' %}?return_url={{ device.get_absolute_url }}">Power Feed</a></li>
</ul> </ul>
</span> </span>
{% endif %} {% endif %}

View File

@ -57,9 +57,17 @@
{% if rearport.cable %} {% if rearport.cable %}
{% include 'dcim/inc/cable_toggle_buttons.html' with cable=rearport.cable %} {% include 'dcim/inc/cable_toggle_buttons.html' with cable=rearport.cable %}
{% elif perms.dcim.add_cable %} {% elif perms.dcim.add_cable %}
<a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk %}?return_url={{ device.get_absolute_url }}" class="btn btn-success btn-xs" title="Connect"> <span class="dropdown">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i> <button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</a> <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='interface' %}?return_url={{ device.get_absolute_url }}">Interface</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='front-port' %}?return_url={{ device.get_absolute_url }}">Front Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='rear-port' %}?return_url={{ device.get_absolute_url }}">Rear Port</a></li>
<li><a href="{% url 'dcim:rearport_connect' termination_a_id=rearport.pk termination_b_type='circuit-termination' %}?return_url={{ device.get_absolute_url }}">Circuit Termination</a></li>
</ul>
</span>
{% endif %} {% endif %}
{% if perms.dcim.change_rearport %} {% if perms.dcim.change_rearport %}
<a href="{% url 'dcim:rearport_edit' pk=rearport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs"> <a href="{% url 'dcim:rearport_edit' pk=rearport.pk %}?return_url={{ device.get_absolute_url }}" title="Edit port" class="btn btn-info btn-xs">