diff --git a/README.md b/README.md index 00ef736..45a3e6a 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Plugin für **NetBox 4.6.5** mit zwei Funktionen: - Beim Speichern einer IP-Adresse wird das durch deren CIDR-Maske beschriebene Prefix gesucht und, falls es fehlt, automatisch erstellt. NetBox ordnet die IP danach nativ anhand von Prefix und VRF ein. - Eine zusätzliche IP-Netzübersicht kann nach Organisation/Region, Standortgruppe, Standort, Lokation, Mandantengruppe und Mandant gefiltert werden. +- Unter **IPAM → Prefixes/IP-Bereiche** legt die Aktion **Alle fehlenden Bereiche anlegen** die Netze für sämtliche bereits vorhandenen, sichtbaren IP-Adressen an. +- Unter **Prefix/IP-Bereich → IP-Adressen** wird das zugehörige Gerät beziehungsweise die VM standardmäßig als eigene Spalte angezeigt. ## Installation @@ -50,7 +52,8 @@ python /opt/netbox/netbox/manage.py reconcile_ip_prefixes Für die Übersicht ist die NetBox-Berechtigung `ipam.view_prefix` erforderlich. Die automatische Erstellung läuft serverseitig; stellen Sie sicher, dass dies zu Ihrem Berechtigungs- und Change-Control-Konzept passt. +Die Aktion für Bestandsdaten benötigt `ipam.view_ipaddress` und `ipam.add_prefix`. Sie verarbeitet nur IP-Adressen, die der ausführende Benutzer sehen darf. + ## Hinweis zu „Organisation" NetBox besitzt kein separates Core-Modell namens Organisation. Die Übersicht bildet Organisation auf NetBox-`Region` ab und bezieht untergeordnete Regionen sowie deren Standorte und Lokationen ein. - diff --git a/netbox_better_ips/__init__.py b/netbox_better_ips/__init__.py index 6e36b60..7a0bac7 100644 --- a/netbox_better_ips/__init__.py +++ b/netbox_better_ips/__init__.py @@ -1,5 +1,4 @@ from .config import BetterIPsConfig -__version__ = "1.0.0" +__version__ = "1.1.0" config = BetterIPsConfig - diff --git a/netbox_better_ips/config.py b/netbox_better_ips/config.py index c523773..ce4e3ee 100644 --- a/netbox_better_ips/config.py +++ b/netbox_better_ips/config.py @@ -6,7 +6,7 @@ class BetterIPsConfig(PluginConfig): verbose_name = "NetBox Better IPs" description = "Automatische Prefix-Zuordnung und erweiterte IP-Netzübersicht" author = "LKE" - version = "1.0.0" + version = "1.1.0" base_url = "better-ips" min_version = "4.6.5" max_version = "4.6.99" @@ -21,4 +21,4 @@ class BetterIPsConfig(PluginConfig): def ready(self): super().ready() from . import signals # noqa: F401 - + from . import tables # noqa: F401 diff --git a/netbox_better_ips/tables.py b/netbox_better_ips/tables.py new file mode 100644 index 0000000..b1c08e3 --- /dev/null +++ b/netbox_better_ips/tables.py @@ -0,0 +1,23 @@ +import django_tables2 as tables +from ipam.tables import AnnotatedIPAddressTable +from utilities.tables import register_table_column + + +device_or_vm = tables.Column( + accessor="assigned_object__parent_object", + linkify=True, + orderable=False, + verbose_name="Gerät / VM", + empty_values=(), +) + +register_table_column(device_or_vm, "device_or_vm", AnnotatedIPAddressTable) + +# Registered columns are selectable but not displayed by default. The annotated +# table is used specifically by Prefix -> IP Addresses, where this information +# should be visible immediately. +if "device_or_vm" not in AnnotatedIPAddressTable.Meta.default_columns: + AnnotatedIPAddressTable.Meta.default_columns = ( + *AnnotatedIPAddressTable.Meta.default_columns, + "device_or_vm", + ) diff --git a/netbox_better_ips/template_content.py b/netbox_better_ips/template_content.py new file mode 100644 index 0000000..cd886ac --- /dev/null +++ b/netbox_better_ips/template_content.py @@ -0,0 +1,11 @@ +from netbox.plugins import PluginTemplateExtension + + +class PrefixListActions(PluginTemplateExtension): + model = "ipam.prefix" + + def list_buttons(self): + return self.render("netbox_better_ips/inc/prefix_list_buttons.html") + + +template_extensions = (PrefixListActions,) diff --git a/netbox_better_ips/templates/netbox_better_ips/inc/prefix_list_buttons.html b/netbox_better_ips/templates/netbox_better_ips/inc/prefix_list_buttons.html new file mode 100644 index 0000000..584bad4 --- /dev/null +++ b/netbox_better_ips/templates/netbox_better_ips/inc/prefix_list_buttons.html @@ -0,0 +1,9 @@ +{% if perms.ipam.view_ipaddress and perms.ipam.add_prefix %} +
+ {% csrf_token %} + +
+{% endif %} diff --git a/netbox_better_ips/urls.py b/netbox_better_ips/urls.py index f7481e8..aef728e 100644 --- a/netbox_better_ips/urls.py +++ b/netbox_better_ips/urls.py @@ -1,10 +1,10 @@ from django.urls import path -from .views import NetworkOverviewView +from .views import NetworkOverviewView, reconcile_missing_prefixes app_name = "netbox_better_ips" urlpatterns = [ path("networks/", NetworkOverviewView.as_view(), name="network_overview"), + path("reconcile/", reconcile_missing_prefixes, name="reconcile_missing_prefixes"), ] - diff --git a/netbox_better_ips/views.py b/netbox_better_ips/views.py index fe028a8..e37ec69 100644 --- a/netbox_better_ips/views.py +++ b/netbox_better_ips/views.py @@ -1,13 +1,18 @@ from django.contrib.contenttypes.models import ContentType +from django.contrib import messages +from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.paginator import Paginator from django.db.models import Q +from django.shortcuts import redirect +from django.views.decorators.http import require_POST from django.views.generic import TemplateView from dcim.models import Location, Region, Site, SiteGroup -from ipam.models import Prefix +from ipam.models import IPAddress, Prefix import netaddr from .forms import NetworkOverviewFilterForm +from .services import ensure_prefix_for_ip def _descendant_ids(obj): @@ -87,3 +92,31 @@ class NetworkOverviewView(PermissionRequiredMixin, TemplateView): } ) return context + + +@require_POST +@permission_required(("ipam.view_ipaddress", "ipam.add_prefix"), raise_exception=True) +def reconcile_missing_prefixes(request): + created = skipped = failed = 0 + addresses = IPAddress.objects.restrict(request.user, "view").select_related( + "tenant", "assigned_object_type" + ) + for address in addresses.iterator(): + try: + prefix, was_created = ensure_prefix_for_ip(address) + created += int(was_created) + skipped += int(prefix is None) + except Exception: + failed += 1 + + if failed: + messages.warning( + request, + f"{created} Bereiche wurden angelegt; {failed} IP-Adressen konnten nicht verarbeitet werden.", + ) + else: + messages.success( + request, + f"{created} fehlende Bereiche wurden angelegt. {skipped} Host-Adressen wurden ignoriert.", + ) + return redirect("ipam:prefix_list") diff --git a/pyproject.toml b/pyproject.toml index 34d82f3..d0f5004 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "netbox-better-ips" -version = "1.0.0" +version = "1.1.0" description = "Automatic prefix creation and an organization-aware IP network overview for NetBox 4.6" readme = "README.md" requires-python = ">=3.12"