jeremystretch 3 лет назад
Родитель
Сommit
5d37f9f975

+ 4 - 11
netbox/dcim/api/serializers.py

@@ -962,14 +962,8 @@ class InventoryItemRoleSerializer(NetBoxModelSerializer):
 
 
 class CableSerializer(NetBoxModelSerializer):
 class CableSerializer(NetBoxModelSerializer):
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
     url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail')
-    termination_a_type = ContentTypeField(
-        queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
-    )
-    termination_b_type = ContentTypeField(
-        queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS)
-    )
-    termination_a = serializers.SerializerMethodField(read_only=True)
-    termination_b = serializers.SerializerMethodField(read_only=True)
+    # termination_a = serializers.SerializerMethodField(read_only=True)
+    # termination_b = serializers.SerializerMethodField(read_only=True)
     status = ChoiceField(choices=LinkStatusChoices, required=False)
     status = ChoiceField(choices=LinkStatusChoices, required=False)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
     tenant = NestedTenantSerializer(required=False, allow_null=True)
     length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False)
     length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False)
@@ -977,9 +971,8 @@ class CableSerializer(NetBoxModelSerializer):
     class Meta:
     class Meta:
         model = Cable
         model = Cable
         fields = [
         fields = [
-            'id', 'url', 'display', 'termination_a_type', 'termination_a_ids', 'termination_a', 'termination_b_type',
-            'termination_b_ids', 'termination_b', 'type', 'status', 'tenant', 'label', 'color', 'length', 'length_unit',
-            'tags', 'custom_fields', 'created', 'last_updated',
+            'id', 'url', 'display', 'type', 'status', 'tenant', 'label', 'color',
+            'length', 'length_unit', 'tags', 'custom_fields', 'created', 'last_updated',
         ]
         ]
 
 
     def _get_termination(self, obj, side):
     def _get_termination(self, obj, side):

+ 53 - 69
netbox/dcim/forms/connections.py

@@ -17,18 +17,47 @@ __all__ = (
 )
 )
 
 
 
 
-class ConnectCableToDeviceForm(TenancyForm, NetBoxModelForm):
-    """
-    Base form for connecting a Cable to a Device component
-    """
-    # Termination A
-    termination_a_ids = DynamicModelMultipleChoiceField(
+class BaseCableConnectionForm(TenancyForm, NetBoxModelForm):
+    a_terminations = DynamicModelMultipleChoiceField(
         queryset=Interface.objects.all(),
         queryset=Interface.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied'
         disabled_indicator='_occupied'
     )
     )
+    b_terminations = DynamicModelMultipleChoiceField(
+        queryset=Interface.objects.all(),
+        label='Name',
+        disabled_indicator='_occupied'
+    )
+
+    def save(self, commit=True):
+        instance = super().save(commit=commit)
+
+        # Create CableTermination instances
+        terminations = []
+        terminations.extend([
+            CableTermination(cable=instance, cable_end='A', termination=termination)
+            for termination in self.cleaned_data['a_terminations']
+        ])
+        terminations.extend([
+            CableTermination(cable=instance, cable_end='B', termination=termination)
+            for termination in self.cleaned_data['b_terminations']
+        ])
 
 
-    # Termination B
+        if commit:
+            CableTermination.objects.bulk_create(terminations)
+        else:
+            instance.terminations = [
+                *self.cleaned_data['a_terminations'],
+                *self.cleaned_data['b_terminations'],
+            ]
+
+        return instance
+
+
+class ConnectCableToDeviceForm(BaseCableConnectionForm):
+    """
+    Base form for connecting a Cable to a Device component
+    """
     termination_b_region = DynamicModelChoiceField(
     termination_b_region = DynamicModelChoiceField(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
         label='Region',
         label='Region',
@@ -83,17 +112,12 @@ class ConnectCableToDeviceForm(TenancyForm, NetBoxModelForm):
             'rack_id': '$termination_b_rack',
             'rack_id': '$termination_b_rack',
         }
         }
     )
     )
-    termination_b_ids = DynamicModelMultipleChoiceField(
-        queryset=Interface.objects.all(),
-        label='Name',
-        disabled_indicator='_occupied'
-    )
 
 
     class Meta:
     class Meta:
         model = Cable
         model = Cable
         fields = [
         fields = [
-            'termination_a_ids', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
-            'termination_b_rack', 'termination_b_device', 'termination_b_ids', 'type', 'status', 'tenant_group',
+            'a_terminations', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
+            'termination_b_rack', 'termination_b_device', 'b_terminations', 'type', 'status', 'tenant_group',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
         ]
         ]
         widgets = {
         widgets = {
@@ -102,17 +126,9 @@ class ConnectCableToDeviceForm(TenancyForm, NetBoxModelForm):
             'length_unit': StaticSelect,
             'length_unit': StaticSelect,
         }
         }
 
 
-    def clean_termination_a_ids(self):
-        # Return the PK rather than the object
-        return [getattr(obj, 'pk') for obj in self.cleaned_data['termination_a_ids']]
-
-    def clean_termination_b_ids(self):
-        # Return the PK rather than the object
-        return [getattr(obj, 'pk') for obj in self.cleaned_data['termination_b_ids']]
-
 
 
 class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
 class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=ConsolePort.objects.all(),
         queryset=ConsolePort.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -123,7 +139,7 @@ class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
 class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=ConsoleServerPort.objects.all(),
         queryset=ConsoleServerPort.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -134,7 +150,7 @@ class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
 class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=PowerPort.objects.all(),
         queryset=PowerPort.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -145,7 +161,7 @@ class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
 class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=PowerOutlet.objects.all(),
         queryset=PowerOutlet.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -156,7 +172,7 @@ class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
 class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=Interface.objects.all(),
         queryset=Interface.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -168,7 +184,7 @@ class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
 class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=FrontPort.objects.all(),
         queryset=FrontPort.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -179,7 +195,7 @@ class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
 
 
 
 
 class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
 class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=RearPort.objects.all(),
         queryset=RearPort.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -189,15 +205,7 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
     )
     )
 
 
 
 
-class ConnectCableToCircuitTerminationForm(TenancyForm, NetBoxModelForm):
-    # Termination A
-    termination_a_ids = DynamicModelMultipleChoiceField(
-        queryset=Interface.objects.all(),
-        label='Side',
-        disabled_indicator='_occupied'
-    )
-
-    # Termination B
+class ConnectCableToCircuitTerminationForm(BaseCableConnectionForm):
     termination_b_provider = DynamicModelChoiceField(
     termination_b_provider = DynamicModelChoiceField(
         queryset=Provider.objects.all(),
         queryset=Provider.objects.all(),
         label='Provider',
         label='Provider',
@@ -236,7 +244,7 @@ class ConnectCableToCircuitTerminationForm(TenancyForm, NetBoxModelForm):
             'site_id': '$termination_b_site',
             'site_id': '$termination_b_site',
         }
         }
     )
     )
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=CircuitTermination.objects.all(),
         queryset=CircuitTermination.objects.all(),
         label='Side',
         label='Side',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -247,29 +255,13 @@ class ConnectCableToCircuitTerminationForm(TenancyForm, NetBoxModelForm):
 
 
     class Meta(ConnectCableToDeviceForm.Meta):
     class Meta(ConnectCableToDeviceForm.Meta):
         fields = [
         fields = [
-            'termination_a_ids', 'termination_b_provider', 'termination_b_region', 'termination_b_sitegroup',
-            'termination_b_site', 'termination_b_circuit', 'termination_b_ids', 'type', 'status', 'tenant_group',
+            'a_terminations', 'termination_b_provider', 'termination_b_region', 'termination_b_sitegroup',
+            'termination_b_site', 'termination_b_circuit', 'b_terminations', 'type', 'status', 'tenant_group',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
         ]
         ]
 
 
-    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 ConnectCableToPowerFeedForm(TenancyForm, NetBoxModelForm):
-    # Termination A
-    termination_a_ids = DynamicModelMultipleChoiceField(
-        queryset=Interface.objects.all(),
-        label='Name',
-        disabled_indicator='_occupied'
-    )
-
-    # Termination B
+class ConnectCableToPowerFeedForm(BaseCableConnectionForm):
     termination_b_region = DynamicModelChoiceField(
     termination_b_region = DynamicModelChoiceField(
         queryset=Region.objects.all(),
         queryset=Region.objects.all(),
         label='Region',
         label='Region',
@@ -312,7 +304,7 @@ class ConnectCableToPowerFeedForm(TenancyForm, NetBoxModelForm):
             'location_id': '$termination_b_location',
             'location_id': '$termination_b_location',
         }
         }
     )
     )
-    termination_b_ids = DynamicModelMultipleChoiceField(
+    b_terminations = DynamicModelMultipleChoiceField(
         queryset=PowerFeed.objects.all(),
         queryset=PowerFeed.objects.all(),
         label='Name',
         label='Name',
         disabled_indicator='_occupied',
         disabled_indicator='_occupied',
@@ -323,15 +315,7 @@ class ConnectCableToPowerFeedForm(TenancyForm, NetBoxModelForm):
 
 
     class Meta(ConnectCableToDeviceForm.Meta):
     class Meta(ConnectCableToDeviceForm.Meta):
         fields = [
         fields = [
-            'termination_a_ids', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
-            'termination_b_location', 'termination_b_powerpanel', 'termination_b_ids', 'type', 'status', 'tenant_group',
+            'a_terminations', 'termination_b_region', 'termination_b_sitegroup', 'termination_b_site',
+            'termination_b_location', 'termination_b_powerpanel', 'b_terminations', 'type', 'status', 'tenant_group',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
             'tenant', 'label', 'color', 'length', 'length_unit', 'tags',
         ]
         ]
-
-    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)

+ 10 - 0
netbox/dcim/models/cables.py

@@ -168,6 +168,16 @@ class Cable(NetBoxModel):
     def get_status_color(self):
     def get_status_color(self):
         return LinkStatusChoices.colors.get(self.status)
         return LinkStatusChoices.colors.get(self.status)
 
 
+    def get_a_terminations(self):
+        return [
+            term.termination for term in CableTermination.objects.filter(cable=self, cable_end='A')
+        ]
+
+    def get_b_terminations(self):
+        return [
+            term.termination for term in CableTermination.objects.filter(cable=self, cable_end='B')
+        ]
+
 
 
 class CableTermination(models.Model):
 class CableTermination(models.Model):
     """
     """

+ 18 - 25
netbox/dcim/signals.py

@@ -81,34 +81,27 @@ def update_connected_endpoints(instance, created, raw=False, **kwargs):
 
 
     # TODO: Update link peer fields
     # TODO: Update link peer fields
     # Cache the Cable on its termination points
     # Cache the Cable on its termination points
-    for term in instance.termination_a:
-        if term.cable != instance:
+    for term in instance.terminations.all():
+        if term.termination.cable != instance:
             logger.debug(f"Updating termination A for cable {instance}: {term}")
             logger.debug(f"Updating termination A for cable {instance}: {term}")
-            term.cable = instance
-            # term._link_peer = instance.termination_b
-            term.save()
-    for term in instance.termination_b:
-        if term.cable != instance:
-            logger.debug(f"Updating termination B for cable {instance}")
-            term.cable = instance
-            # term._link_peer = instance.termination_a
+            term.termination.cable = instance
             term.save()
             term.save()
 
 
-    # Create/update cable paths
-    if created:
-        for termination in [*instance.termination_a, *instance.termination_b]:
-            if isinstance(termination, PathEndpoint):
-                create_cablepath(termination)
-            else:
-                rebuild_paths(termination)
-    elif instance.status != instance._orig_status:
-        # We currently don't support modifying either termination of an existing Cable. (This
-        # may change in the future.) However, we do need to capture status changes and update
-        # any CablePaths accordingly.
-        if instance.status != LinkStatusChoices.STATUS_CONNECTED:
-            CablePath.objects.filter(path__contains=instance).update(is_active=False)
-        else:
-            rebuild_paths(instance)
+    # # Create/update cable paths
+    # if created:
+    #     for term in instance.terminations.all():
+    #         if isinstance(term.termination, PathEndpoint):
+    #             create_cablepath(term.termination)
+    #         else:
+    #             rebuild_paths(term.termination)
+    # elif instance.status != instance._orig_status:
+    #     # We currently don't support modifying either termination of an existing Cable. (This
+    #     # may change in the future.) However, we do need to capture status changes and update
+    #     # any CablePaths accordingly.
+    #     if instance.status != LinkStatusChoices.STATUS_CONNECTED:
+    #         CablePath.objects.filter(path__contains=instance).update(is_active=False)
+    #     else:
+    #         rebuild_paths(instance)
 
 
 
 
 @receiver(post_delete, sender=Cable)
 @receiver(post_delete, sender=Cable)

+ 25 - 25
netbox/dcim/tables/template_code.py

@@ -139,9 +139,9 @@ CONSOLEPORT_BUTTONS = """
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
         </button>
         </button>
         <ul class="dropdown-menu dropdown-menu-end">
         <ul class="dropdown-menu dropdown-menu-end">
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Console Server Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Front Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Rear Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Console Server Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Front Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_consoleports' pk=object.pk %}">Rear Port</a></li>
         </ul>
         </ul>
     </span>
     </span>
 {% else %}
 {% else %}
@@ -171,9 +171,9 @@ CONSOLESERVERPORT_BUTTONS = """
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
         </button>
         </button>
         <ul class="dropdown-menu dropdown-menu-end">
         <ul class="dropdown-menu dropdown-menu-end">
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Console Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Front Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Rear Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Console Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Front Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}">Rear Port</a></li>
         </ul>
         </ul>
     </span>
     </span>
 {% else %}
 {% else %}
@@ -203,8 +203,8 @@ POWERPORT_BUTTONS = """
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
         </button>
         </button>
         <ul class="dropdown-menu dropdown-menu-end">
         <ul class="dropdown-menu dropdown-menu-end">
-            <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.poweroutlet&return_url={% url 'dcim:device_powerports' pk=object.pk %}">Power Outlet</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.powerfeed&return_url={% url 'dcim:device_powerports' pk=object.pk %}">Power Feed</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.poweroutlet&return_url={% url 'dcim:device_powerports' pk=object.pk %}">Power Outlet</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:powerport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.powerfeed&return_url={% url 'dcim:device_powerports' pk=object.pk %}">Power Feed</a></li>
         </ul>
         </ul>
     </span>
     </span>
 {% else %}
 {% else %}
@@ -230,7 +230,7 @@ POWEROUTLET_BUTTONS = """
     <a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
     <a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i></a>
     <a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
     <a href="#" class="btn btn-outline-dark btn-sm disabled"><i class="mdi mdi-lan-connect" aria-hidden="true"></i></a>
     {% if not record.mark_connected %}
     {% if not record.mark_connected %}
-        <a href="{% url 'dcim:poweroutlet_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.powerport&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" title="Connect" class="btn btn-success btn-sm">
+        <a href="{% url 'dcim:poweroutlet_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.powerport&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" title="Connect" class="btn btn-success btn-sm">
             <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i>
             <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i>
         </a>
         </a>
     {% else %}
     {% else %}
@@ -280,10 +280,10 @@ INTERFACE_BUTTONS = """
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
         </button>
         </button>
         <ul class="dropdown-menu dropdown-menu-end">
         <ul class="dropdown-menu dropdown-menu-end">
-            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Interface</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Front Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Rear Port</a></li>
-            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=circuits.circuittermination&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Circuit Termination</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Interface</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Front Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Rear Port</a></li>
+            <li><a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ record.pk }}&termination_b_type=circuits.circuittermination&return_url={% url 'dcim:device_interfaces' pk=object.pk %}">Circuit Termination</a></li>
         </ul>
         </ul>
     </span>
     </span>
     {% else %}
     {% else %}
@@ -319,12 +319,12 @@ FRONTPORT_BUTTONS = """
                 <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
                 <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             </button>
             </button>
             <ul class="dropdown-menu dropdown-menu-end">
             <ul class="dropdown-menu dropdown-menu-end">
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Interface</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Console Server Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Console Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Front Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Rear Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=circuits.circuittermination&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Circuit Termination</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Interface</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Console Server Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Console Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Front Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Rear Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=circuits.circuittermination&return_url={% url 'dcim:device_frontports' pk=object.pk %}">Circuit Termination</a></li>
             </ul>
             </ul>
         </span>
         </span>
     {% else %}
     {% else %}
@@ -356,12 +356,12 @@ REARPORT_BUTTONS = """
                 <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
                 <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span>
             </button>
             </button>
             <ul class="dropdown-menu dropdown-menu-end">
             <ul class="dropdown-menu dropdown-menu-end">
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Interface</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Console Server Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Console Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Front Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Rear Port</a></li>
-                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ record.pk }}&termination_b_type=circuits.circuitterminations&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Circuit Termination</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.interface&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Interface</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleserverport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Console Server Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.consoleport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Console Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.frontport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Front Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=dcim.rearport&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Rear Port</a></li>
+                <li><a class="dropdown-item" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ record.pk }}&termination_b_type=circuits.circuitterminations&return_url={% url 'dcim:device_rearports' pk=object.pk %}">Circuit Termination</a></li>
             </ul>
             </ul>
         </span>
         </span>
     {% else %}
     {% else %}

+ 10 - 15
netbox/dcim/views.py

@@ -2829,24 +2829,14 @@ class CableCreateView(generic.ObjectEditView):
         # Always return a new instance
         # Always return a new instance
         return self.queryset.model()
         return self.queryset.model()
 
 
-    def alter_object(self, obj, request, url_args, url_kwargs):
-        termination_a_type = url_kwargs.get('termination_a_type')
-        termination_a_ids = request.GET.get('termination_a_ids', [])
-        app_label, model = request.GET.get('termination_b_type').split('.')
-        self.termination_b_type = ContentType.objects.get(app_label=app_label, model=model)
-
-        # Initialize Cable termination attributes
-        obj.termination_a_type = ContentType.objects.get_for_model(termination_a_type)
-        obj.termination_a_ids = termination_a_type.objects.filter(pk__in=termination_a_ids)
-        obj.termination_b_type = self.termination_b_type
-
-        return obj
-
     def get(self, request, *args, **kwargs):
     def get(self, request, *args, **kwargs):
         obj = self.get_object(**kwargs)
         obj = self.get_object(**kwargs)
         obj = self.alter_object(obj, request, args, kwargs)
         obj = self.alter_object(obj, request, args, kwargs)
         initial_data = request.GET
         initial_data = request.GET
 
 
+        app_label, model = request.GET.get('termination_b_type').split('.')
+        termination_b_type = ContentType.objects.get(app_label=app_label, model=model)
+
         # TODO
         # TODO
         # # Set initial site and rack based on side A termination (if not already set)
         # # Set initial site and rack based on side A termination (if not already set)
         # termination_a_site = getattr(obj.termination_a.parent_object, 'site', None)
         # termination_a_site = getattr(obj.termination_a.parent_object, 'site', None)
@@ -2857,12 +2847,17 @@ class CableCreateView(generic.ObjectEditView):
         form = self.form(instance=obj, initial=initial_data)
         form = self.form(instance=obj, initial=initial_data)
 
 
         # Set the queryset of termination A
         # Set the queryset of termination A
-        form.fields['termination_a_ids'].queryset = kwargs['termination_a_type'].objects.all()
+        form.fields['a_terminations'].queryset = kwargs['termination_a_type'].objects.all()
+
+        # TODO Find a better way to infer the near-end parent object
+        termination_a = kwargs['termination_a_type'].objects.filter(pk__in=initial_data['a_terminations']).first()
 
 
         return render(request, self.template_name, {
         return render(request, self.template_name, {
             'obj': obj,
             'obj': obj,
             'obj_type': Cable._meta.verbose_name,
             'obj_type': Cable._meta.verbose_name,
-            'termination_b_type': self.termination_b_type.name,
+            'termination_a_type': kwargs['termination_a_type']._meta.model_name,
+            'termination_a': termination_a,
+            'termination_b_type': termination_b_type.name,
             'form': form,
             'form': form,
             'return_url': self.get_return_url(request, obj),
             'return_url': self.get_return_url(request, obj),
         })
         })

+ 4 - 4
netbox/templates/circuits/inc/circuit_termination.html

@@ -70,10 +70,10 @@
                       <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
                       <span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
                     </button>
                     </button>
                     <ul class="dropdown-menu">
                     <ul class="dropdown-menu">
-                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?termination_a_id={{ termination.pk }}&termination_b_type=dcim.interface&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Interface</a></li>
-                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?termination_a_id={{ termination.pk }}&termination_b_type=dcim.frontport&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Front Port</a></li>
-                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?termination_a_id={{ termination.pk }}&termination_b_type=dcim.rearport&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Rear Port</a></li>
-                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?termination_a_id={{ termination.pk }}&termination_b_type=circuits.circuittermination&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
+                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?a_terminations={{ termination.pk }}&termination_b_type=dcim.interface&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Interface</a></li>
+                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?a_terminations={{ termination.pk }}&termination_b_type=dcim.frontport&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Front Port</a></li>
+                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?a_terminations={{ termination.pk }}&termination_b_type=dcim.rearport&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Rear Port</a></li>
+                      <li><a class="dropdown-item" href="{% url 'circuits:circuittermination_connect' %}?a_terminations={{ termination.pk }}&termination_b_type=circuits.circuittermination&termination_b_site={{ termination.site.pk }}&return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
                     </ul>
                     </ul>
                   </div>
                   </div>
                 {% endif %}
                 {% endif %}

+ 2 - 2
netbox/templates/dcim/cable.html

@@ -63,13 +63,13 @@
       <div class="card">
       <div class="card">
         <h5 class="card-header">Termination A</h5>
         <h5 class="card-header">Termination A</h5>
         <div class="card-body">
         <div class="card-body">
-          {% include 'dcim/inc/cable_termination.html' with termination=object.termination_a %}
+          {% include 'dcim/inc/cable_termination.html' with terminations=object.get_a_terminations %}
         </div>
         </div>
       </div>
       </div>
       <div class="card">
       <div class="card">
         <h5 class="card-header">Termination B</h5>
         <h5 class="card-header">Termination B</h5>
         <div class="card-body">
         <div class="card-body">
-          {% include 'dcim/inc/cable_termination.html' with termination=object.termination_b %}
+          {% include 'dcim/inc/cable_termination.html' with terminations=object.get_b_terminations %}
         </div>
         </div>
       </div>
       </div>
       {% plugin_right_page object %}
       {% plugin_right_page object %}

+ 25 - 27
netbox/templates/dcim/cable_connect.html

@@ -15,9 +15,8 @@
 
 
 {% block content-wrapper %}
 {% block content-wrapper %}
   <div class="tab-content">
   <div class="tab-content">
-    {% with termination_a=form.instance.termination_a.0 %}
-      {% render_errors form %}
-      <form method="post">
+    {% render_errors form %}
+    <form method="post">
       {% csrf_token %}
       {% csrf_token %}
       {% for field in form.hidden_fields %}
       {% for field in form.hidden_fields %}
           {{ field }}
           {{ field }}
@@ -27,7 +26,27 @@
               <div class="card h-100">
               <div class="card h-100">
                   <h5 class="card-header offset-sm-3">A Side</h5>
                   <h5 class="card-header offset-sm-3">A Side</h5>
                   <div class="card-body">
                   <div class="card-body">
-                      {% if termination_a.device %}
+                      {% if termination_a_type == 'circuit' %}
+                          {# Circuit termination #}
+                          <div class="row mb-3">
+                              <label class="col-sm-3 col-form-label text-lg-end">Site</label>
+                              <div class="col">
+                                  <input class="form-control" value="{{ termination_a.site }}" disabled />
+                              </div>
+                          </div>
+                          <div class="row mb-3">
+                              <label class="col-sm-3 col-form-label text-lg-end">Provider</label>
+                              <div class="col">
+                                  <input class="form-control" value="{{ termination_a.circuit.provider }}" disabled />
+                              </div>
+                          </div>
+                          <div class="row mb-3">
+                              <label class="col-sm-3 col-form-label text-lg-end">Circuit</label>
+                              <div class="col">
+                                  <input class="form-control" value="{{ termination_a.circuit.cid }}" disabled />
+                              </div>
+                          </div>
+                      {% else %}
                           {# Device component #}
                           {# Device component #}
                           <div class="row mb-3">
                           <div class="row mb-3">
                               <label class="col-sm-3 col-form-label text-lg-end">Region</label>
                               <label class="col-sm-3 col-form-label text-lg-end">Region</label>
@@ -71,28 +90,8 @@
                                   <input class="form-control" value="{{ termination_a|meta:"verbose_name"|capfirst }}" disabled />
                                   <input class="form-control" value="{{ termination_a|meta:"verbose_name"|capfirst }}" disabled />
                               </div>
                               </div>
                           </div>
                           </div>
-                      {% else %}
-                          {# Circuit termination #}
-                          <div class="row mb-3">
-                              <label class="col-sm-3 col-form-label text-lg-end">Site</label>
-                              <div class="col">
-                                  <input class="form-control" value="{{ termination_a.site }}" disabled />
-                              </div>
-                          </div>
-                          <div class="row mb-3">
-                              <label class="col-sm-3 col-form-label text-lg-end">Provider</label>
-                              <div class="col">
-                                  <input class="form-control" value="{{ termination_a.circuit.provider }}" disabled />
-                              </div>
-                          </div>
-                          <div class="row mb-3">
-                              <label class="col-sm-3 col-form-label text-lg-end">Circuit</label>
-                              <div class="col">
-                                  <input class="form-control" value="{{ termination_a.circuit.cid }}" disabled />
-                              </div>
-                          </div>
                       {% endif %}
                       {% endif %}
-                      {% render_field form.termination_a_ids %}
+                      {% render_field form.a_terminations %}
                   </div>
                   </div>
               </div>
               </div>
           </div>
           </div>
@@ -148,7 +147,7 @@
                               <input class="form-control" value="{{ termination_b_type|capfirst }}" disabled />
                               <input class="form-control" value="{{ termination_b_type|capfirst }}" disabled />
                           </div>
                           </div>
                       </div>
                       </div>
-                      {% render_field form.termination_b_ids %}
+                      {% render_field form.b_terminations %}
                   </div>
                   </div>
               </div>
               </div>
           </div>
           </div>
@@ -170,6 +169,5 @@
         </div>
         </div>
       </div>
       </div>
     </form>
     </form>
-    {% endwith %}
   </div>
   </div>
 {% endblock %}
 {% endblock %}

+ 3 - 3
netbox/templates/dcim/consoleport.html

@@ -113,7 +113,7 @@
                                         <li>
                                         <li>
                                             <a
                                             <a
                                                 class="dropdown-item"
                                                 class="dropdown-item"
-                                                href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.consoleserverport&return_url={{ object.get_absolute_url }}"
+                                                href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.consoleserverport&return_url={{ object.get_absolute_url }}"
                                             >
                                             >
                                                 Console Server Port
                                                 Console Server Port
                                             </a>
                                             </a>
@@ -121,7 +121,7 @@
                                         <li>
                                         <li>
                                             <a
                                             <a
                                                 class="dropdown-item"
                                                 class="dropdown-item"
-                                                href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}"
+                                                href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}"
                                             >
                                             >
                                                 Front Port
                                                 Front Port
                                             </a>
                                             </a>
@@ -129,7 +129,7 @@
                                         <li>
                                         <li>
                                             <a
                                             <a
                                                 class="dropdown-item"
                                                 class="dropdown-item"
-                                                href="{% url 'dcim:consoleport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}"
+                                                href="{% url 'dcim:consoleport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}"
                                             >
                                             >
                                                 Rear Port
                                                 Rear Port
                                             </a>
                                             </a>

+ 3 - 3
netbox/templates/dcim/consoleserverport.html

@@ -115,7 +115,7 @@
                                     <li>
                                     <li>
                                         <a
                                         <a
                                             class="dropdown-item"
                                             class="dropdown-item"
-                                            href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.consoleport&return_url={{ object.get_absolute_url }}"
+                                            href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.consoleport&return_url={{ object.get_absolute_url }}"
                                         >
                                         >
                                             Console Port
                                             Console Port
                                         </a>
                                         </a>
@@ -123,7 +123,7 @@
                                     <li>
                                     <li>
                                         <a
                                         <a
                                             class="dropdown-item"
                                             class="dropdown-item"
-                                            href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}"
+                                            href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}"
                                         >
                                         >
                                             Front Port
                                             Front Port
                                         </a>
                                         </a>
@@ -131,7 +131,7 @@
                                     <li>
                                     <li>
                                         <a
                                         <a
                                             class="dropdown-item"
                                             class="dropdown-item"
-                                            href="{% url 'dcim:consoleserverport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}"
+                                            href="{% url 'dcim:consoleserverport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}"
                                         >
                                         >
                                             Rear Port
                                             Rear Port
                                         </a>
                                         </a>

+ 6 - 6
netbox/templates/dcim/frontport.html

@@ -105,22 +105,22 @@
                                 </button>
                                 </button>
                                 <ul class="dropdown-menu dropdown-menu-end">
                                 <ul class="dropdown-menu dropdown-menu-end">
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">Interface</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">Interface</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.consoleserverport&return_url={{ object.get_absolute_url }}">Console Server Port</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.consoleserverport&return_url={{ object.get_absolute_url }}">Console Server Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.consoleport&return_url={{ object.get_absolute_url }}">Console Port</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.consoleport&return_url={{ object.get_absolute_url }}">Console Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">Front Port</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">Front Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">Rear Port</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">Rear Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">Circuit Termination</a>
+                                        <a class="dropdown-item" href="{% url 'dcim:frontport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">Circuit Termination</a>
                                     </li>
                                     </li>
                                 </ul>
                                 </ul>
                             </div>
                             </div>

+ 10 - 10
netbox/templates/dcim/inc/cable_termination.html

@@ -1,29 +1,29 @@
 {% load helpers %}
 {% load helpers %}
 <table class="table table-hover panel-body attr-table">
 <table class="table table-hover panel-body attr-table">
-  {% if termination.0.device %}
+  {% if terminations.0.device %}
     {# Device component #}
     {# Device component #}
     <tr>
     <tr>
       <td>Device</td>
       <td>Device</td>
-      <td>{{ termination.0.device|linkify }}</td>
+      <td>{{ terminations.0.device|linkify }}</td>
     </tr>
     </tr>
     <tr>
     <tr>
       <td>Site</td>
       <td>Site</td>
-      <td>{{ termination.0.device.site|linkify }}</td>
+      <td>{{ terminations.0.device.site|linkify }}</td>
     </tr>
     </tr>
-    {% if termination.0.device.rack %}
+    {% if terminations.0.device.rack %}
       <tr>
       <tr>
         <td>Rack</td>
         <td>Rack</td>
-        <td>{{ termination.0.device.rack|linkify }}</td>
+        <td>{{ terminations.0.device.rack|linkify }}</td>
       </tr>
       </tr>
     {% endif %}
     {% endif %}
     <tr>
     <tr>
       <td>Type</td>
       <td>Type</td>
-      <td>{{ termination.0|meta:"verbose_name"|capfirst }}</td>
+      <td>{{ terminations.0|meta:"verbose_name"|capfirst }}</td>
     </tr>
     </tr>
     <tr>
     <tr>
-      <td>Component(s)</td>
+      <td>Name(s)</td>
       <td>
       <td>
-        {% for term in termination %}
+        {% for term in terminations %}
           {{ term|linkify }}{% if not forloop.last %},{% endif %}
           {{ term|linkify }}{% if not forloop.last %},{% endif %}
         {% endfor %}
         {% endfor %}
       </td>
       </td>
@@ -32,12 +32,12 @@
     {# Circuit termination #}
     {# Circuit termination #}
     <tr>
     <tr>
       <td>Provider</td>
       <td>Provider</td>
-      <td>{{ termination.0.circuit.provider|linkify }}</td>
+      <td>{{ terminations.0.circuit.provider|linkify }}</td>
     </tr>
     </tr>
     <tr>
     <tr>
       <td>Circuit</td>
       <td>Circuit</td>
       <td>
       <td>
-        {% for term in termination %}
+        {% for term in terminations %}
           {{ term.circuit|linkify }} ({{ term }}){% if not forloop.last %},{% endif %}
           {{ term.circuit|linkify }} ({{ term }}){% if not forloop.last %},{% endif %}
         {% endfor %}
         {% endfor %}
       </td>
       </td>

+ 4 - 4
netbox/templates/dcim/interface.html

@@ -251,22 +251,22 @@
                     </button>
                     </button>
                     <ul class="dropdown-menu dropdown-menu-end">
                     <ul class="dropdown-menu dropdown-menu-end">
                       <li>
                       <li>
-                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">
+                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">
                           Interface
                           Interface
                         </a>
                         </a>
                       </li>
                       </li>
                       <li>
                       <li>
-                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">
+                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">
                           Front Port
                           Front Port
                         </a>
                         </a>
                       </li>
                       </li>
                       <li>
                       <li>
-                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">
+                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">
                           Rear Port
                           Rear Port
                         </a>
                         </a>
                       </li>
                       </li>
                       <li>
                       <li>
-                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">
+                        <a class="dropdown-item" href="{% url 'dcim:interface_connect' %}?a_terminations={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">
                           Circuit Termination
                           Circuit Termination
                         </a>
                         </a>
                       </li>
                       </li>

+ 1 - 1
netbox/templates/dcim/powerfeed.html

@@ -158,7 +158,7 @@
             {% if not object.mark_connected and not object.cable %}
             {% if not object.mark_connected and not object.cable %}
             <div class="card-footer">
             <div class="card-footer">
             {% if perms.dcim.add_cable %}
             {% if perms.dcim.add_cable %}
-                <a href="{% url 'dcim:powerfeed_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.powerport&return_url={{ object.get_absolute_url }}"
+                <a href="{% url 'dcim:powerfeed_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.powerport&return_url={{ object.get_absolute_url }}"
                 class="btn btn-primary btn-sm float-end">
                 class="btn btn-primary btn-sm float-end">
                     <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i> Connect
                     <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i> Connect
                 </a>
                 </a>

+ 1 - 1
netbox/templates/dcim/poweroutlet.html

@@ -111,7 +111,7 @@
                     <div class="text-muted">
                     <div class="text-muted">
                         Not Connected
                         Not Connected
                         {% if perms.dcim.add_cable %}
                         {% if perms.dcim.add_cable %}
-                            <a href="{% url 'dcim:poweroutlet_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.powerport&return_url={{ object.get_absolute_url }}" title="Connect" class="btn btn-primary btn-sm float-end">
+                            <a href="{% url 'dcim:poweroutlet_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.powerport&return_url={{ object.get_absolute_url }}" title="Connect" class="btn btn-primary btn-sm float-end">
                                 <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i> Connect
                                 <i class="mdi mdi-ethernet-cable" aria-hidden="true"></i> Connect
                             </a>
                             </a>
                         {% endif %}
                         {% endif %}

+ 2 - 2
netbox/templates/dcim/powerport.html

@@ -117,10 +117,10 @@
                                 </button>
                                 </button>
                                 <ul class="dropdown-menu dropdown-menu-end">
                                 <ul class="dropdown-menu dropdown-menu-end">
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:powerport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.poweroutlet&return_url={{ object.get_absolute_url }}">Power Outlet</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:powerport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.poweroutlet&return_url={{ object.get_absolute_url }}">Power Outlet</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:powerport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.powerfeed&return_url={{ object.get_absolute_url }}">Power Feed</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:powerport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.powerfeed&return_url={{ object.get_absolute_url }}">Power Feed</a>
                                     </li>
                                     </li>
                                 </ul>
                                 </ul>
                             </span>
                             </span>

+ 4 - 4
netbox/templates/dcim/rearport.html

@@ -101,16 +101,16 @@
                                 </button>
                                 </button>
                                 <ul class="dropdown-menu dropdown-menu-end">
                                 <ul class="dropdown-menu dropdown-menu-end">
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">Interface</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.interface&return_url={{ object.get_absolute_url }}">Interface</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">Front Port</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.frontport&return_url={{ object.get_absolute_url }}">Front Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">Rear Port</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=dcim.rearport&return_url={{ object.get_absolute_url }}">Rear Port</a>
                                     </li>
                                     </li>
                                     <li>
                                     <li>
-                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?termination_a_id={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">Circuit Termination</a>
+                                        <a class="dropdown-link" href="{% url 'dcim:rearport_connect' %}?a_terminations={{ object.pk }}&termination_b_type=circuits.circuittermination&return_url={{ object.get_absolute_url }}">Circuit Termination</a>
                                     </li>
                                     </li>
                                 </ul>
                                 </ul>
                             </span>
                             </span>