1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

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

This commit is contained in:
Jeremy Stretch
2018-01-30 16:34:42 -05:00
parent 2f7f5425d8
commit 1cd629efb3
3 changed files with 23 additions and 16 deletions

View File

@ -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:
self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
device_id=self.data['device'], form_factor=IFACE_FF_LAG
)
device = Device.objects.get(pk=self.data['device'])
else:
self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
device=self.instance.device, form_factor=IFACE_FF_LAG
device__in=[device, device.get_vc_master()], form_factor=IFACE_FF_LAG
)
else:
device = self.instance.device
self.fields['lag'].queryset = Interface.objects.order_naturally().filter(
device__in=[self.instance.device, self.instance.device.get_vc_master()], form_factor=IFACE_FF_LAG
)
# 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 = []

View File

@ -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

View File

@ -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 %}