Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions netbox/ipam/models/ip.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,14 @@ def get_next_available_ip(self):
if available_ips:
return next(iter(available_ips))

def get_related_ips(self):
"""
Return all IPAddresses belonging to the same VRF.
"""
return IPAddress.objects.exclude(address=str(self.address)).filter(
vrf=self.vrf, address__net_contained_or_equal=str(self.address)
)

def clean(self):
super().clean()

Expand Down
28 changes: 18 additions & 10 deletions netbox/ipam/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -755,19 +755,9 @@ def get_extra_context(self, request, instance):
# Limit to a maximum of 10 duplicates displayed here
duplicate_ips_table = tables.IPAddressTable(duplicate_ips[:10], orderable=False)

# Related IP table
related_ips = IPAddress.objects.restrict(request.user, 'view').exclude(
address=str(instance.address)
).filter(
vrf=instance.vrf, address__net_contained_or_equal=str(instance.address)
)
related_ips_table = tables.IPAddressTable(related_ips, orderable=False)
related_ips_table.configure(request)

return {
'parent_prefixes_table': parent_prefixes_table,
'duplicate_ips_table': duplicate_ips_table,
'related_ips_table': related_ips_table,
}


Expand Down Expand Up @@ -872,6 +862,24 @@ class IPAddressBulkDeleteView(generic.BulkDeleteView):
table = tables.IPAddressTable


@register_model_view(IPAddress, 'related_ips', path='related-ip-addresses')
class IPAddressRelatedIPsView(generic.ObjectChildrenView):
queryset = IPAddress.objects.prefetch_related('vrf__tenant', 'tenant')
child_model = IPAddress
table = tables.IPAddressTable
filterset = filtersets.IPAddressFilterSet
template_name = 'ipam/ipaddress/ip_addresses.html'
tab = ViewTab(
label=_('Related IPs'),
badge=lambda x: x.get_related_ips().count(),
weight=500,
hide_if_empty=True,
)

def get_children(self, request, parent):
return parent.get_related_ips().restrict(request.user, 'view')


#
# VLAN groups
#
Expand Down
8 changes: 0 additions & 8 deletions netbox/templates/ipam/ipaddress.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
{% load plugins %}
{% load render_table from django_tables2 %}

{% block breadcrumbs %}
{{ block.super }}
{% if object.vrf %}
<li class="breadcrumb-item"><a href="{% url 'ipam:ipaddress_list' %}?vrf_id={{ object.vrf.pk }}">{{ object.vrf }}</a></li>
{% endif %}
{% endblock %}

{% block content %}
<div class="row">
<div class="col col-md-4">
Expand Down Expand Up @@ -116,7 +109,6 @@ <h5 class="card-header">
{% if duplicate_ips_table.rows %}
{% include 'inc/panel_table.html' with table=duplicate_ips_table heading='Duplicate IPs' panel_class='danger' %}
{% endif %}
{% include 'inc/panel_table.html' with table=related_ips_table heading='Related IPs' %}
<div class="card">
<h5 class="card-header">Services</h5>
<div class="card-body htmx-container table-responsive"
Expand Down
8 changes: 8 additions & 0 deletions netbox/templates/ipam/ipaddress/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends 'generic/object.html' %}

{% block breadcrumbs %}
{{ block.super }}
{% if object.vrf %}
<li class="breadcrumb-item"><a href="{% url 'ipam:ipaddress_list' %}?vrf_id={{ object.vrf.pk }}">{{ object.vrf }}</a></li>
{% endif %}
{% endblock %}
19 changes: 19 additions & 0 deletions netbox/templates/ipam/ipaddress/ip_addresses.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{% extends 'ipam/ipaddress/base.html' %}
{% load helpers %}

{% block content %}
{% include 'inc/table_controls_htmx.html' with table_modal="IPAddressTable_config" %}
<form method="post">
{% csrf_token %}
<div class="card">
<div class="card-body" id="object_list">
{% include 'htmx/table.html' %}
</div>
</div>
</form>
{% endblock content %}

{% block modals %}
{{ block.super }}
{% table_config_form table %}
{% endblock modals %}