Просмотр исходного кода

Enable filtering FHRP groups by related IP addresses

jeremystretch 4 лет назад
Родитель
Сommit
f48d7aedce

+ 24 - 0
netbox/ipam/filtersets.py

@@ -624,6 +624,10 @@ class FHRPGroupFilterSet(PrimaryModelFilterSet):
     auth_type = django_filters.MultipleChoiceFilter(
     auth_type = django_filters.MultipleChoiceFilter(
         choices=FHRPGroupAuthTypeChoices
         choices=FHRPGroupAuthTypeChoices
     )
     )
+    related_ip = django_filters.ModelMultipleChoiceFilter(
+        queryset=IPAddress.objects.all(),
+        method='filter_related_ip'
+    )
     tag = TagFilter()
     tag = TagFilter()
 
 
     class Meta:
     class Meta:
@@ -637,6 +641,26 @@ class FHRPGroupFilterSet(PrimaryModelFilterSet):
             Q(description__icontains=value)
             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):
 class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet):
     content_type = ContentTypeFilter()
     content_type = ContentTypeFilter()

+ 7 - 0
netbox/ipam/forms/models.py

@@ -546,6 +546,13 @@ class FHRPGroupAssignmentForm(BootstrapMixin, forms.ModelForm):
         model = FHRPGroupAssignment
         model = FHRPGroupAssignment
         fields = ('group', 'priority')
         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):
 class VLANGroupForm(BootstrapMixin, CustomFieldModelForm):
     scope_type = ContentTypeChoiceField(
     scope_type = ContentTypeChoiceField(

+ 1 - 1
netbox/ipam/migrations/0052_fhrpgroup.py

@@ -44,7 +44,7 @@ class Migration(migrations.Migration):
                 ('last_updated', models.DateTimeField(auto_now=True, null=True)),
                 ('last_updated', models.DateTimeField(auto_now=True, null=True)),
                 ('id', models.BigAutoField(primary_key=True, serialize=False)),
                 ('id', models.BigAutoField(primary_key=True, serialize=False)),
                 ('object_id', models.PositiveIntegerField()),
                 ('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')),
                 ('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')),
                 ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ipam.fhrpgroup')),
             ],
             ],

+ 1 - 0
netbox/ipam/models/fhrp.py

@@ -82,6 +82,7 @@ class FHRPGroupAssignment(ChangeLoggedModel):
     )
     )
     priority = models.PositiveSmallIntegerField(
     priority = models.PositiveSmallIntegerField(
         blank=True,
         blank=True,
+        null=True
     )
     )
 
 
     objects = RestrictedQuerySet.as_manager()
     objects = RestrictedQuerySet.as_manager()

+ 11 - 7
netbox/ipam/tables/fhrp.py

@@ -1,8 +1,6 @@
 import django_tables2 as tables
 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 *
 from ipam.models import *
 
 
 __all__ = (
 __all__ = (
@@ -47,8 +45,11 @@ class FHRPGroupTable(BaseTable):
 
 
 class FHRPGroupAssignmentTable(BaseTable):
 class FHRPGroupAssignmentTable(BaseTable):
     pk = ToggleColumn()
     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(
     object = tables.Column(
         linkify=True,
         linkify=True,
@@ -57,8 +58,11 @@ class FHRPGroupAssignmentTable(BaseTable):
     group = tables.Column(
     group = tables.Column(
         linkify=True
         linkify=True
     )
     )
+    actions = ButtonsColumn(
+        model=FHRPGroupAssignment,
+        buttons=('edit', 'delete', 'foo')
+    )
 
 
     class Meta(BaseTable.Meta):
     class Meta(BaseTable.Meta):
         model = FHRPGroupAssignment
         model = FHRPGroupAssignment
-        fields = ('pk', 'content_type', 'object', 'group', 'priority')
-        default_columns = ('pk', 'content_type', 'object', 'group', 'priority')
+        fields = ('pk', 'group', 'object_parent', 'object', 'priority')

+ 4 - 4
netbox/ipam/views.py

@@ -849,12 +849,12 @@ class FHRPGroupView(generic.ObjectView):
             orderable=False
             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')
         members_table.columns.hide('group')
-        paginate_table(members_table, request)
 
 
         return {
         return {
             'ipaddress_table': ipaddress_table,
             'ipaddress_table': ipaddress_table,

+ 1 - 36
netbox/templates/dcim/interface.html

@@ -440,42 +440,7 @@
                     </div>
                     </div>
                 </div>
                 </div>
             {% endif %}
             {% endif %}
-            <div class="card">
-                <h5 class="card-header">NHRP Groups</h5>
-                <div class="card-body">
-                    <table class="table table-hover table-headings">
-                        <thead>
-                            <tr>
-                                <th>Group</th>
-                                <th>Priority</th>
-                            </tr>
-                        </thead>
-                        <tbody>
-                            {% for assignment in object.fhrp_group_assignments.all %}
-                                <tr>
-                                    <td>
-                                        <a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group }}</a>
-                                    </td>
-                                    <td>
-                                        {{ assignment.priority }}
-                                    </td>
-                                </tr>
-                            {% empty %}
-                                <tr>
-                                    <td colspan="3" class="text-muted">None</td>
-                                </tr>
-                            {% endfor %}
-                        </tbody>
-                    </table>
-                </div>
-                {% if perms.ipam.add_fhrpgroupassignment %}
-                    <div class="card-footer text-end noprint">
-                        <a href="{% url 'ipam:fhrpgroupassignment_add' %}?content_type=dcim.interface&object_id={{ object.pk }}" class="btn btn-sm btn-primary">
-                            <span class="mdi mdi-plus-thick" aria-hidden="true"></span> New Assignment
-                        </a>
-                    </div>
-                {% endif %}
-            </div>
+            {% include 'ipam/inc/panels/fhrp_groups.html' %}
             {% plugin_right_page object %}
             {% plugin_right_page object %}
         </div>
         </div>
     </div>
     </div>

+ 5 - 3
netbox/templates/ipam/fhrpgroup.html

@@ -72,10 +72,12 @@
       <div class="card">
       <div class="card">
         <h5 class="card-header">Members</h5>
         <h5 class="card-header">Members</h5>
         <div class="card-body">
         <div class="card-body">
-          {% include 'inc/table.html' with table=members_table %}
+          {% if ipaddress_table.rows %}
+            {% render_table members_table 'inc/table.html' %}
+          {% else %}
+            <div class="text-muted">None</div>
+          {% endif %}
         </div>
         </div>
-      </div>
-      {% include 'inc/paginator.html' with paginator=members_table.paginator page=members_table.page %}
       {% plugin_full_width_page object %}
       {% plugin_full_width_page object %}
     </div>
     </div>
   </div>
   </div>

+ 45 - 0
netbox/templates/ipam/inc/panels/fhrp_groups.html

@@ -0,0 +1,45 @@
+{% load helpers %}
+
+<div class="card">
+  <h5 class="card-header">NHRP Groups</h5>
+  <div class="card-body">
+    <table class="table table-hover table-headings">
+      <thead>
+        <tr>
+          <th>Group</th>
+          <th>Virtual IPs</th>
+          <th>Priority</th>
+        </tr>
+      </thead>
+      <tbody>
+        {% for assignment in object.fhrp_group_assignments.all %}
+          <tr>
+            <td>
+              <a href="{{ assignment.group.get_absolute_url }}">{{ assignment.group }}</a>
+            </td>
+            <td>
+              {% for ipaddress in assignment.group.ip_addresses.all %}
+                <a href="{{ ipaddress.get_absolute_url }}">{{ ipaddress }}</a>
+                {% if not forloop.last %}<br />{% endif %}
+              {% endfor %}
+            </td>
+            <td>
+              {{ assignment.priority }}
+            </td>
+          </tr>
+        {% empty %}
+          <tr>
+            <td colspan="3" class="text-muted">None</td>
+          </tr>
+        {% endfor %}
+      </tbody>
+    </table>
+  </div>
+  {% if perms.ipam.add_fhrpgroupassignment %}
+    <div class="card-footer text-end noprint">
+      <a href="{% url 'ipam:fhrpgroupassignment_add' %}?content_type={{ object|meta:"app_label" }}.{{ object|meta:"model_name" }}&object_id={{ object.pk }}" class="btn btn-sm btn-primary">
+        <span class="mdi mdi-plus-thick" aria-hidden="true"></span> Assign Group
+      </a>
+    </div>
+  {% endif %}
+</div>

+ 2 - 1
netbox/templates/virtualization/vminterface.html

@@ -76,11 +76,12 @@
                 </table>
                 </table>
             </div>
             </div>
         </div>
         </div>
+        {% include 'inc/panels/tags.html' %}
         {% plugin_left_page object %}
         {% plugin_left_page object %}
     </div>
     </div>
     <div class="col col-md-6">
     <div class="col col-md-6">
         {% include 'inc/panels/custom_fields.html' %}
         {% include 'inc/panels/custom_fields.html' %}
-        {% include 'inc/panels/tags.html' %}
+        {% include 'ipam/inc/panels/fhrp_groups.html' %}
         {% plugin_right_page object %}
         {% plugin_right_page object %}
     </div>
     </div>
 </div>
 </div>