mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-31 04:46:26 -06:00
feat: add cable reconnection
This commit is contained in:
parent
4f7626828a
commit
f8d7c024e7
@ -4269,6 +4269,574 @@ class CableCSVForm(CustomFieldModelCSVForm):
|
||||
return length_unit if length_unit is not None else ''
|
||||
|
||||
|
||||
class ReconnectCableToDeviceForm(BootstrapMixin, forms.ModelForm):
|
||||
"""
|
||||
Base form for connecting a Cable to a Device component
|
||||
"""
|
||||
termination_a_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False,
|
||||
)
|
||||
termination_a_rack = DynamicModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
label='Rack',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site_id': '$termination_a_site'
|
||||
}
|
||||
)
|
||||
termination_a_device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
query_params={
|
||||
'site_id': '$termination_a_site',
|
||||
'rack_id': '$termination_a_rack',
|
||||
}
|
||||
)
|
||||
termination_b_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_b_rack = DynamicModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
label='Rack',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site_id': '$termination_b_site'
|
||||
}
|
||||
)
|
||||
termination_b_device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
query_params={
|
||||
'site_id': '$termination_b_site',
|
||||
'rack_id': '$termination_b_rack',
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'termination_a_site', 'termination_a_rack', 'termination_a_device', 'termination_a_id',
|
||||
'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_id'
|
||||
]
|
||||
|
||||
def clean_termination_a_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_a_id'], 'pk', None)
|
||||
|
||||
def clean_termination_b_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_b_id'], 'pk', None)
|
||||
|
||||
|
||||
class ReconnectConsolePortToConsoleServerPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=ConsolePort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=ConsoleServerPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectConsolePortToFrontPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=ConsolePort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectConsolePortToRearPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=ConsolePort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectConsoleServerPortToFrontPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=ConsoleServerPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectConsoleServerPortToRearPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=ConsoleServerPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectPowerfeedToPowerPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False,
|
||||
display_field='cid'
|
||||
)
|
||||
termination_a_rackgroup = DynamicModelChoiceField(
|
||||
queryset=Location.objects.all(),
|
||||
label='Location',
|
||||
required=False,
|
||||
display_field='cid',
|
||||
query_params={
|
||||
'site_id': '$termination_a_site'
|
||||
}
|
||||
)
|
||||
termination_a_powerpanel = DynamicModelChoiceField(
|
||||
queryset=PowerPanel.objects.all(),
|
||||
label='Power Panel',
|
||||
required=False,
|
||||
query_params={
|
||||
'site_id': '$termination_a_site',
|
||||
'rack_group_id': '$termination_a_rackgroup',
|
||||
}
|
||||
)
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=PowerFeed.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'power_panel_id': '$termination_a_powerpanel'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=PowerPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'termination_a_site', 'termination_a_rackgroup', 'termination_a_powerpanel', 'termination_a_id',
|
||||
'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_id'
|
||||
]
|
||||
|
||||
|
||||
class ReconnectPowerOutletToPowerPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=PowerOutlet.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=PowerPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectInterfaceForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device',
|
||||
'kind': 'physical',
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device',
|
||||
'kind': 'physical',
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectFrontPortToInterfaceForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device',
|
||||
'kind': 'physical',
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectInterfaceToRearPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device',
|
||||
'kind': 'physical',
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectCircuitTerminationToInterfaceForm(ReconnectCableToDeviceForm):
|
||||
termination_a_provider = DynamicModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider',
|
||||
required=False
|
||||
)
|
||||
termination_a_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_a_circuit = DynamicModelChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
display_field='cid',
|
||||
query_params={
|
||||
'provider_id': '$termination_a_provider',
|
||||
'site_id': '$termination_a_site',
|
||||
}
|
||||
)
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=CircuitTermination.objects.all(),
|
||||
label='Side',
|
||||
display_field='term_side',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'circuit_id': '$termination_a_circuit'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=Interface.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device',
|
||||
'kind': 'physical',
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'termination_a_provider', 'termination_a_site', 'termination_a_circuit', 'termination_a_id',
|
||||
'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_id'
|
||||
]
|
||||
|
||||
|
||||
class ReconnectCircuitTerminationForm(BootstrapMixin, forms.ModelForm):
|
||||
termination_a_provider = DynamicModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider',
|
||||
required=False
|
||||
)
|
||||
termination_a_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_a_circuit = DynamicModelChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
display_field='cid',
|
||||
query_params={
|
||||
'provider_id': '$termination_a_provider',
|
||||
'site_id': '$termination_a_site',
|
||||
}
|
||||
)
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=CircuitTermination.objects.all(),
|
||||
label='Side',
|
||||
display_field='term_side',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'circuit_id': '$termination_a_circuit'
|
||||
}
|
||||
)
|
||||
termination_b_provider = DynamicModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider',
|
||||
required=False
|
||||
)
|
||||
termination_b_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_b_circuit = DynamicModelChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
display_field='cid',
|
||||
query_params={
|
||||
'provider_id': '$termination_b_provider',
|
||||
'site_id': '$termination_b_site',
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=CircuitTermination.objects.all(),
|
||||
label='Side',
|
||||
display_field='term_side',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'circuit_id': '$termination_b_circuit'
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'termination_a_provider', 'termination_a_site', 'termination_a_circuit', 'termination_a_id',
|
||||
'termination_b_provider', 'termination_b_site', 'termination_b_circuit', 'termination_b_id', 'type',
|
||||
'status', 'label', 'color', 'length', 'length_unit',
|
||||
]
|
||||
|
||||
def clean_termination_a_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_a_id'], 'pk', None)
|
||||
|
||||
def clean_termination_b_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_b_id'], 'pk', None)
|
||||
|
||||
|
||||
class ReconnectFrontPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectFrontPortToRearPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectRearPortForm(ReconnectCableToDeviceForm):
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_a_device'
|
||||
}
|
||||
)
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectCircuitTerminationToForm(BootstrapMixin, forms.ModelForm):
|
||||
termination_a_provider = DynamicModelChoiceField(
|
||||
queryset=Provider.objects.all(),
|
||||
label='Provider',
|
||||
required=False
|
||||
)
|
||||
termination_a_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_a_circuit = DynamicModelChoiceField(
|
||||
queryset=Circuit.objects.all(),
|
||||
label='Circuit',
|
||||
display_field='cid',
|
||||
query_params={
|
||||
'provider_id': '$termination_a_provider',
|
||||
'site_id': '$termination_a_site',
|
||||
}
|
||||
)
|
||||
termination_a_id = DynamicModelChoiceField(
|
||||
queryset=CircuitTermination.objects.all(),
|
||||
label='Side',
|
||||
display_field='term_side',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'circuit_id': '$termination_a_circuit'
|
||||
}
|
||||
)
|
||||
termination_b_site = DynamicModelChoiceField(
|
||||
queryset=Site.objects.all(),
|
||||
label='Site',
|
||||
required=False
|
||||
)
|
||||
termination_b_rack = DynamicModelChoiceField(
|
||||
queryset=Rack.objects.all(),
|
||||
label='Rack',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
null_option='None',
|
||||
query_params={
|
||||
'site_id': '$termination_b_site'
|
||||
}
|
||||
)
|
||||
termination_b_device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
label='Device',
|
||||
required=False,
|
||||
display_field='display_name',
|
||||
query_params={
|
||||
'site_id': '$termination_b_site',
|
||||
'rack_id': '$termination_b_rack',
|
||||
}
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Cable
|
||||
fields = [
|
||||
'termination_a_provider', 'termination_a_site', 'termination_a_circuit', 'termination_a_id',
|
||||
'termination_b_site', 'termination_b_rack', 'termination_b_device', 'termination_b_id'
|
||||
]
|
||||
|
||||
def clean_termination_a_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_a_id'], 'pk', None)
|
||||
|
||||
def clean_termination_b_id(self):
|
||||
# Return the PK rather than the object
|
||||
return getattr(self.cleaned_data['termination_b_id'], 'pk', None)
|
||||
|
||||
|
||||
class ReconnectCircuitTerminationToFrontPortForm(ReconnectCircuitTerminationToForm):
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=FrontPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ReconnectCircuitTerminationToRearPortForm(ReconnectCircuitTerminationToForm):
|
||||
termination_b_id = DynamicModelChoiceField(
|
||||
queryset=RearPort.objects.all(),
|
||||
label='Name',
|
||||
disabled_indicator='cable',
|
||||
query_params={
|
||||
'device_id': '$termination_b_device'
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class CableBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=Cable.objects.all(),
|
||||
|
@ -378,6 +378,7 @@ urlpatterns = [
|
||||
path('cables/<int:pk>/delete/', views.CableDeleteView.as_view(), name='cable_delete'),
|
||||
path('cables/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='cable_changelog', kwargs={'model': Cable}),
|
||||
path('cables/<int:pk>/journal/', ObjectJournalView.as_view(), name='cable_journal', kwargs={'model': Cable}),
|
||||
path(r'cables/<int:pk>/reconnect/', views.CableReconnectView.as_view(), name='cable_reconnect'),
|
||||
|
||||
# Console/power/interface connections (read-only)
|
||||
path('console-connections/', views.ConsoleConnectionsListView.as_view(), name='console_connections_list'),
|
||||
|
@ -2478,6 +2478,104 @@ class CableBulkDeleteView(generic.BulkDeleteView):
|
||||
table = tables.CableTable
|
||||
|
||||
|
||||
class CableReconnectView(ObjectPermissionRequiredMixin, GetReturnURLMixin, View):
|
||||
queryset = Cable.objects.prefetch_related('termination_a', 'termination_b')
|
||||
template_name = 'dcim/cable_reconnect.html'
|
||||
|
||||
def get_required_permission(self):
|
||||
return 'dcim.change_cable'
|
||||
|
||||
def dispatch(self, request, *args, pk=None, **kwargs):
|
||||
self.obj = Cable.objects.get(pk=pk)
|
||||
|
||||
idx = (self.obj.termination_a_type.model, self.obj.termination_b_type.model)
|
||||
idx_sorted = tuple(sorted(idx))
|
||||
if idx != idx_sorted:
|
||||
termination_a = self.obj.termination_a
|
||||
self.obj.termination_a = self.obj.termination_b
|
||||
self.obj.termination_b = termination_a
|
||||
|
||||
self.form_class = {
|
||||
('circuittermination', 'circuittermination'): forms.ReconnectCircuitTerminationForm,
|
||||
('circuittermination', 'rearport'): forms.ReconnectCircuitTerminationToRearPortForm,
|
||||
('consoleport', 'consoleserverport'): forms.ReconnectConsolePortToConsoleServerPortForm,
|
||||
('consoleport', 'frontport'): forms.ReconnectConsolePortToFrontPortForm,
|
||||
('consoleport', 'rearport'): forms.ReconnectConsolePortToRearPortForm,
|
||||
('consoleserverport', 'frontport'): forms.ReconnectConsoleServerPortToFrontPortForm,
|
||||
('consoleserverport', 'rearport'): forms.ReconnectConsoleServerPortToRearPortForm,
|
||||
('powerfeed', 'powerport'): forms.ReconnectPowerfeedToPowerPortForm,
|
||||
('poweroutlet', 'powerport'): forms.ReconnectPowerOutletToPowerPortForm,
|
||||
('circuittermination', 'interface'): forms.ReconnectCircuitTerminationToInterfaceForm,
|
||||
('frontport', 'interface'): forms.ReconnectFrontPortToInterfaceForm,
|
||||
('interface', 'rearport'): forms.ReconnectInterfaceToRearPortForm,
|
||||
('interface', 'interface'): forms.ReconnectInterfaceForm,
|
||||
('frontport', 'frontport'): forms.ReconnectFrontPortForm,
|
||||
('frontport', 'rearport'): forms.ReconnectFrontPortToRearPortForm,
|
||||
('circuittermination', 'frontport'): forms.ReconnectCircuitTerminationToFrontPortForm,
|
||||
('rearport', 'rearport'): forms.ReconnectRearPortForm,
|
||||
}[idx_sorted]
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def prefill_form(self, initial_data, termination):
|
||||
o = getattr(self.obj, termination)
|
||||
if o and hasattr(o, 'device'):
|
||||
device = o.device
|
||||
initial_data['{}_device'.format(termination)] = device
|
||||
if device.site:
|
||||
initial_data['{}_site'.format(termination)] = device.site
|
||||
if device.rack:
|
||||
initial_data['{}_rack'.format(termination)] = device.rack
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
# Parse initial data manually to avoid setting field values as lists
|
||||
initial_data = {k: request.GET[k] for k in request.GET}
|
||||
|
||||
self.prefill_form(initial_data, 'termination_a')
|
||||
self.prefill_form(initial_data, 'termination_b')
|
||||
|
||||
form = self.form_class(instance=self.obj, initial=initial_data)
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'obj': self.obj,
|
||||
'obj_type': Cable._meta.verbose_name,
|
||||
'form': form,
|
||||
'return_url': self.get_return_url(request, self.obj),
|
||||
})
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
try:
|
||||
if hasattr(self.obj.termination_a, '_path') and self.obj.termination_a._path_id:
|
||||
self.obj.termination_a._path = None
|
||||
except CablePath.DoesNotExist:
|
||||
pass
|
||||
try:
|
||||
if hasattr(self.obj.termination_b, '_path') and self.obj.termination_b._path_id:
|
||||
self.obj.termination_b._path = None
|
||||
except CablePath.DoesNotExist:
|
||||
pass
|
||||
self.obj.delete()
|
||||
|
||||
self.obj.termination_a.cable = None
|
||||
self.obj.termination_b.cable = None
|
||||
|
||||
form = self.form_class(request.POST, request.FILES, instance=self.obj)
|
||||
if form.is_valid():
|
||||
obj = form.save()
|
||||
|
||||
return redirect(self.get_return_url(request, obj))
|
||||
|
||||
return render(request, self.template_name, {
|
||||
'obj': self.obj,
|
||||
'obj_type': Cable._meta.verbose_name,
|
||||
'form': form,
|
||||
|
||||
|
||||
'return_url': self.get_return_url(request, self.obj),
|
||||
})
|
||||
|
||||
|
||||
#
|
||||
# Connections
|
||||
#
|
||||
|
@ -10,6 +10,10 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block buttons %}
|
||||
{% if request.user|can_change:object %}
|
||||
<a href="{% url 'dcim:cable_reconnect' pk=object.pk %}" class="btn btn-primary">
|
||||
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Reconnect </a>
|
||||
{% endif %}
|
||||
{% if request.user|can_change:object %}
|
||||
{% edit_button object %}
|
||||
{% endif %}
|
||||
|
140
netbox/templates/dcim/cable_reconnect.html
Normal file
140
netbox/templates/dcim/cable_reconnect.html
Normal file
@ -0,0 +1,140 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
{% load helpers %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" class="form form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% for field in form.hidden_fields %}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading"><strong>Errors</strong></div>
|
||||
<div class="panel-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% with termination_a=form.instance.termination_a %}
|
||||
<h3>{% block title %}Reconnect {{ form.instance.termination_a_type.name|bettertitle }}<->{{ form.instance.termination_b_type.name|bettertitle }} cable{% endblock %}</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading text-center">
|
||||
<strong>A Side</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% 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_a_provider' in form.fields %}
|
||||
{% render_field form.termination_a_provider %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_site' in form.fields %}
|
||||
{% render_field form.termination_a_site %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_rackgroup' in form.fields %}
|
||||
{% render_field form.termination_a_rackgroup %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_rack' in form.fields %}
|
||||
{% render_field form.termination_a_rack %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_device' in form.fields %}
|
||||
{% render_field form.termination_a_device %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_type' in form.fields %}
|
||||
{% render_field form.termination_a_type %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_powerpanel' in form.fields %}
|
||||
{% render_field form.termination_a_powerpanel %}
|
||||
{% endif %}
|
||||
{% if 'termination_a_circuit' in form.fields %}
|
||||
{% render_field form.termination_a_circuit %}
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label required">Type</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-static">{{ form.instance.termination_a_type.name|capfirst }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% render_field form.termination_a_id %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2 text-center" style="padding-top: 90px;">
|
||||
<i class="fa fa-exchange fa-4x"></i>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading text-center">
|
||||
<strong>B Side</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% 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 %}
|
||||
{% render_field form.termination_b_site %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_rackgroup' in form.fields %}
|
||||
{% render_field form.termination_b_rackgroup %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_rack' in form.fields %}
|
||||
{% render_field form.termination_b_rack %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_device' in form.fields %}
|
||||
{% render_field form.termination_b_device %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_type' in form.fields %}
|
||||
{% render_field form.termination_b_type %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_powerpanel' in form.fields %}
|
||||
{% render_field form.termination_b_powerpanel %}
|
||||
{% endif %}
|
||||
{% if 'termination_b_circuit' in form.fields %}
|
||||
{% render_field form.termination_b_circuit %}
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label required">Type</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-static">{{ form.instance.termination_b_type.name|capfirst }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% render_field form.termination_b_id %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: none">
|
||||
{% include 'dcim/inc/cable_form.html' %}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-12 text-center">
|
||||
<button type="submit" name="_update" class="btn btn-primary">Reconnect</button>
|
||||
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="{% static 'js/livesearch.js' %}?v{{ settings.VERSION }}"></script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user