diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py index 89bb61c02..5d385c7ef 100644 --- a/netbox/ipam/filtersets.py +++ b/netbox/ipam/filtersets.py @@ -624,6 +624,10 @@ class FHRPGroupFilterSet(PrimaryModelFilterSet): auth_type = django_filters.MultipleChoiceFilter( choices=FHRPGroupAuthTypeChoices ) + related_ip = django_filters.ModelMultipleChoiceFilter( + queryset=IPAddress.objects.all(), + method='filter_related_ip' + ) tag = TagFilter() class Meta: @@ -637,6 +641,26 @@ class FHRPGroupFilterSet(PrimaryModelFilterSet): Q(description__icontains=value) ) + def filter_related_ip(self, queryset, name, value): + """ + Filter by VRF & prefix of assigned IP addresses. + """ + ip_filter = Q() + for ipaddress in value: + if ipaddress.vrf: + q = Q( + ip_addresses__address__net_contained_or_equal=ipaddress.address, + ip_addresses__vrf=ipaddress.vrf + ) + else: + q = Q( + ip_addresses__address__net_contained_or_equal=ipaddress.address, + ip_addresses__vrf__isnull=True + ) + ip_filter |= q + + return queryset.filter(ip_filter) + class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet): content_type = ContentTypeFilter() diff --git a/netbox/ipam/forms/models.py b/netbox/ipam/forms/models.py index 36a078071..c605a7b7c 100644 --- a/netbox/ipam/forms/models.py +++ b/netbox/ipam/forms/models.py @@ -546,6 +546,13 @@ class FHRPGroupAssignmentForm(BootstrapMixin, forms.ModelForm): model = FHRPGroupAssignment fields = ('group', 'priority') + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + ipaddresses = self.instance.object.ip_addresses.all() + for ipaddress in ipaddresses: + self.fields['group'].widget.add_query_param('related_ip', ipaddress.pk) + class VLANGroupForm(BootstrapMixin, CustomFieldModelForm): scope_type = ContentTypeChoiceField( diff --git a/netbox/ipam/migrations/0052_fhrpgroup.py b/netbox/ipam/migrations/0052_fhrpgroup.py index f61191a7e..17d4ec9ca 100644 --- a/netbox/ipam/migrations/0052_fhrpgroup.py +++ b/netbox/ipam/migrations/0052_fhrpgroup.py @@ -44,7 +44,7 @@ class Migration(migrations.Migration): ('last_updated', models.DateTimeField(auto_now=True, null=True)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('object_id', models.PositiveIntegerField()), - ('priority', models.PositiveSmallIntegerField(blank=True)), + ('priority', models.PositiveSmallIntegerField(blank=True, null=True)), ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ipam.fhrpgroup')), ], diff --git a/netbox/ipam/models/fhrp.py b/netbox/ipam/models/fhrp.py index c108032b4..01ab6b5f8 100644 --- a/netbox/ipam/models/fhrp.py +++ b/netbox/ipam/models/fhrp.py @@ -82,6 +82,7 @@ class FHRPGroupAssignment(ChangeLoggedModel): ) priority = models.PositiveSmallIntegerField( blank=True, + null=True ) objects = RestrictedQuerySet.as_manager() diff --git a/netbox/ipam/tables/fhrp.py b/netbox/ipam/tables/fhrp.py index e3411cd7e..8aae4bba7 100644 --- a/netbox/ipam/tables/fhrp.py +++ b/netbox/ipam/tables/fhrp.py @@ -1,8 +1,6 @@ import django_tables2 as tables -from utilities.tables import ( - BaseTable, ContentTypeColumn, MarkdownColumn, TagColumn, ToggleColumn, -) +from utilities.tables import BaseTable, ButtonsColumn, MarkdownColumn, TagColumn, ToggleColumn from ipam.models import * __all__ = ( @@ -47,8 +45,11 @@ class FHRPGroupTable(BaseTable): class FHRPGroupAssignmentTable(BaseTable): pk = ToggleColumn() - content_type = ContentTypeColumn( - verbose_name='Object Type' + object_parent = tables.Column( + accessor=tables.A('object.parent_object'), + linkify=True, + orderable=False, + verbose_name='Parent' ) object = tables.Column( linkify=True, @@ -57,8 +58,11 @@ class FHRPGroupAssignmentTable(BaseTable): group = tables.Column( linkify=True ) + actions = ButtonsColumn( + model=FHRPGroupAssignment, + buttons=('edit', 'delete', 'foo') + ) class Meta(BaseTable.Meta): model = FHRPGroupAssignment - fields = ('pk', 'content_type', 'object', 'group', 'priority') - default_columns = ('pk', 'content_type', 'object', 'group', 'priority') + fields = ('pk', 'group', 'object_parent', 'object', 'priority') diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index b4864577d..8746787fe 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -849,12 +849,12 @@ class FHRPGroupView(generic.ObjectView): orderable=False ) - group_assignments = FHRPGroupAssignment.objects.restrict(request.user, 'view').filter( - group=instance + # Get assigned interfaces + members_table = tables.FHRPGroupAssignmentTable( + data=FHRPGroupAssignment.objects.restrict(request.user, 'view').filter(group=instance), + orderable=False ) - members_table = tables.FHRPGroupAssignmentTable(group_assignments) members_table.columns.hide('group') - paginate_table(members_table, request) return { 'ipaddress_table': ipaddress_table, diff --git a/netbox/templates/dcim/interface.html b/netbox/templates/dcim/interface.html index a6dc1a901..f4ab30e4d 100644 --- a/netbox/templates/dcim/interface.html +++ b/netbox/templates/dcim/interface.html @@ -440,42 +440,7 @@ {% endif %} -
Group | -Priority | -|
---|---|---|
- {{ assignment.group }} - | -- {{ assignment.priority }} - | -|
None | -
Group | +Virtual IPs | +Priority | +
---|---|---|
+ {{ assignment.group }} + | +
+ {% for ipaddress in assignment.group.ip_addresses.all %}
+ {{ ipaddress }}
+ {% if not forloop.last %} {% endif %} + {% endfor %} + |
+ + {{ assignment.priority }} + | +
None | +