Browse Source

#1843: Allow assignment of VC member interfaces to VC master LAG

Jeremy Stretch 7 years ago
parent
commit
1cd629efb3
3 changed files with 22 additions and 15 deletions
  1. 9 9
      netbox/dcim/forms.py
  2. 11 2
      netbox/dcim/models.py
  3. 2 4
      netbox/templates/dcim/inc/interface.html

+ 9 - 9
netbox/dcim/forms.py

@@ -1706,17 +1706,17 @@ class InterfaceForm(BootstrapMixin, forms.ModelForm, ChainedFieldsMixin):
     def __init__(self, *args, **kwargs):
         super(InterfaceForm, self).__init__(*args, **kwargs)
 
-        # Limit LAG choices to interfaces belonging to this device
+        # Limit LAG choices to interfaces belonging to this device (or VC master)
         if self.is_bound:
+            device = Device.objects.get(pk=self.data['device'])
             self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
-                device_id=self.data['device'], form_factor=IFACE_FF_LAG
+                device__in=[device, device.get_vc_master()], form_factor=IFACE_FF_LAG
             )
-            device = Device.objects.get(pk=self.data['device'])
         else:
+            device = self.instance.device
             self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
-                device=self.instance.device, form_factor=IFACE_FF_LAG
+                device__in=[self.instance.device, self.instance.device.get_vc_master()], form_factor=IFACE_FF_LAG
             )
-            device = self.instance.device
 
         # Limit the queryset for the site to only include the interface's device's site
         if device and device.site:
@@ -1832,10 +1832,10 @@ class InterfaceCreateForm(ComponentForm, ChainedFieldsMixin):
 
         super(InterfaceCreateForm, self).__init__(*args, **kwargs)
 
-        # Limit LAG choices to interfaces belonging to this device
+        # Limit LAG choices to interfaces belonging to this device (or its VC master)
         if self.parent is not None:
             self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
-                device=self.parent, form_factor=IFACE_FF_LAG
+                device__in=[self.parent, self.parent.get_vc_master()], form_factor=IFACE_FF_LAG
             )
         else:
             self.fields['lag'].queryset = Interface.objects.none()
@@ -1935,7 +1935,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm, ChainedFieldsMixin):
     def __init__(self, *args, **kwargs):
         super(InterfaceBulkEditForm, self).__init__(*args, **kwargs)
 
-        # Limit LAG choices to interfaces which belong to the parent device.
+        # Limit LAG choices to interfaces which belong to the parent device (or VC master)
         device = None
         if self.initial.get('device'):
             try:
@@ -1945,7 +1945,7 @@ class InterfaceBulkEditForm(BootstrapMixin, BulkEditForm, ChainedFieldsMixin):
         if device is not None:
             interface_ordering = device.device_type.interface_ordering
             self.fields['lag'].queryset = Interface.objects.order_naturally(method=interface_ordering).filter(
-                device=device, form_factor=IFACE_FF_LAG
+                device__in=[device, device.get_vc_master()], form_factor=IFACE_FF_LAG
             )
         else:
             self.fields['lag'].choices = []

+ 11 - 2
netbox/dcim/models.py

@@ -1070,6 +1070,15 @@ class Device(CreatedUpdatedModel, CustomFieldModel):
         else:
             return None
 
+    def get_vc_master(self):
+        """
+        If this Device is a VirtualChassis member, return the VC master. Otherwise, return None.
+        """
+        if hasattr(self, 'vc_membership'):
+            return self.vc_membership.virtual_chassis.master
+        else:
+            return None
+
     @property
     def virtual_chassis(self):
         try:
@@ -1375,8 +1384,8 @@ class Interface(models.Model):
                                "Disconnect the interface or choose a suitable form factor."
             })
 
-        # An interface's LAG must belong to the same device
-        if self.lag and self.lag.device != self.device:
+        # An interface's LAG must belong to the same device (or VC master)
+        if self.lag and self.lag.device not in [self.device, self.device.get_vc_master()]:
             raise ValidationError({
                 'lag': "The selected LAG interface ({}) belongs to a different device ({}).".format(
                     self.lag.name, self.lag.device.name

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

@@ -1,11 +1,9 @@
 <tr class="interface{% if not iface.enabled %} danger{% elif iface.connection and iface.connection.connection_status or iface.circuit_termination %} success{% elif iface.connection and not iface.connection.connection_status %} info{% elif iface.is_virtual %} warning{% endif %}" id="iface_{{ iface.name }}">
 
-    {# Checkbox (exclude VC members) #}
+    {# Checkbox #}
     {% if perms.dcim.change_interface or perms.dcim.delete_interface %}
         <td class="pk">
-            {% if iface.parent == device %}
-                <input name="pk" type="checkbox" value="{{ iface.pk }}" />
-            {% endif %}
+            <input name="pk" type="checkbox" value="{{ iface.pk }}" />
         </td>
     {% endif %}