fix: IP-Bereiche mit korrekten Adresstypen erstellen

- Start- und Endadressen als netaddr-Objekte übergeben
- Fehler einzelner IP-Adressen beim Abgleich protokollieren
- IP-Netzübersicht direkt im IPAM-Menü registrieren
- Plugin-Version auf 1.2.1 erhöhen
This commit is contained in:
2026-07-23 12:17:14 +02:00
parent 8be6978d81
commit d904d335a9
7 changed files with 47 additions and 20 deletions
+1
View File
@@ -6,6 +6,7 @@ Plugin für **NetBox 4.6.5** mit zwei Funktionen:
- Eine zusätzliche IP-Netzübersicht kann nach Organisation/Region, Standortgruppe, Standort, Lokation, Mandantengruppe und Mandant gefiltert werden. - Eine zusätzliche IP-Netzübersicht kann nach Organisation/Region, Standortgruppe, Standort, Lokation, Mandantengruppe und Mandant gefiltert werden.
- Unter **IPAM → IP-Bereiche** legt die Aktion **Alle fehlenden Bereiche anlegen** die Bereiche für sämtliche bereits vorhandenen, sichtbaren IP-Adressen an. - Unter **IPAM → IP-Bereiche** legt die Aktion **Alle fehlenden Bereiche anlegen** die Bereiche für sämtliche bereits vorhandenen, sichtbaren IP-Adressen an.
- Unter **IP-Bereich → IP-Adressen** wird das zugehörige Gerät beziehungsweise die VM standardmäßig als eigene Spalte angezeigt. - Unter **IP-Bereich → IP-Adressen** wird das zugehörige Gerät beziehungsweise die VM standardmäßig als eigene Spalte angezeigt.
- Die **IP-Netzübersicht** ist als eigener Eintrag direkt im Menü **IPAM** verfügbar.
## Installation ## Installation
+1 -1
View File
@@ -1,4 +1,4 @@
from .config import BetterIPsConfig from .config import BetterIPsConfig
__version__ = "1.2.0" __version__ = "1.2.1"
config = BetterIPsConfig config = BetterIPsConfig
+4 -1
View File
@@ -6,7 +6,7 @@ class BetterIPsConfig(PluginConfig):
verbose_name = "NetBox Better IPs" verbose_name = "NetBox Better IPs"
description = "Automatische Prefix-Zuordnung und erweiterte IP-Netzübersicht" description = "Automatische Prefix-Zuordnung und erweiterte IP-Netzübersicht"
author = "LKE" author = "LKE"
version = "1.2.0" version = "1.2.1"
base_url = "better-ips" base_url = "better-ips"
min_version = "4.6.5" min_version = "4.6.5"
max_version = "4.6.99" max_version = "4.6.99"
@@ -21,3 +21,6 @@ class BetterIPsConfig(PluginConfig):
super().ready() super().ready()
from . import signals # noqa: F401 from . import signals # noqa: F401
from . import tables # noqa: F401 from . import tables # noqa: F401
from .navigation import register_ipam_menu_item
register_ipam_menu_item()
@@ -11,12 +11,17 @@ class Command(BaseCommand):
parser.add_argument("--dry-run", action="store_true") parser.add_argument("--dry-run", action="store_true")
def handle(self, *args, **options): def handle(self, *args, **options):
created = skipped = 0 created = skipped = failed = 0
for address in IPAddress.objects.select_related("tenant", "assigned_object_type").iterator(): for address in IPAddress.objects.select_related("tenant", "assigned_object_type").iterator():
ip_range, was_created = ensure_range_for_ip(address) try:
if options["dry_run"] and was_created: ip_range, was_created = ensure_range_for_ip(address)
ip_range.delete() if options["dry_run"] and was_created:
created += int(was_created) ip_range.delete()
skipped += int(ip_range is None) created += int(was_created)
skipped += int(ip_range is None)
except Exception as exc:
failed += 1
self.stderr.write(f"Fehler bei {address}: {exc}")
verb = "würden erstellt" if options["dry_run"] else "erstellt" verb = "würden erstellt" if options["dry_run"] else "erstellt"
self.stdout.write(self.style.SUCCESS(f"{created} IP-Bereiche {verb}; {skipped} Hostmasken ignoriert.")) message = f"{created} IP-Bereiche {verb}; {skipped} Hostmasken ignoriert; {failed} Fehler."
self.stdout.write(self.style.SUCCESS(message) if not failed else self.style.WARNING(message))
+23 -8
View File
@@ -1,10 +1,25 @@
from netbox.plugins import PluginMenuItem from netbox.navigation import MenuItem
menu_items = (
PluginMenuItem(
link="plugins:netbox_better_ips:network_overview",
link_text="IP-Netzübersicht",
permissions=["ipam.view_prefix"],
),
)
# The public plugin navigation API can only create a separate Plugins menu.
# NetBox 4.6.5 does not expose an API for extending an existing core menu, so
# this pinned-version integration appends our entry to IPAM's first group.
def register_ipam_menu_item():
from netbox.navigation.menu import IPAM_MENU
group = IPAM_MENU.groups[0]
link = "plugins:netbox_better_ips:network_overview"
if any(item.link == link for item in group.items):
return
group.items = (
*group.items,
MenuItem(
link=link,
link_text="IP-Netzübersicht",
permissions=["ipam.view_prefix"],
),
)
# Do not duplicate the entry in NetBox's generic Plugins menu.
menu_items = ()
+5 -2
View File
@@ -1,6 +1,7 @@
import ipaddress import ipaddress
import logging import logging
import netaddr
from django.db import transaction from django.db import transaction
from ipam.models import IPRange from ipam.models import IPRange
from netbox.plugins import get_plugin_config from netbox.plugins import get_plugin_config
@@ -46,8 +47,10 @@ def ensure_range_for_ip(ip, *, config=None):
elif network.version == 6 and network.prefixlen < 127: elif network.version == 6 and network.prefixlen < 127:
first += 1 first += 1
start_address = f"{ipaddress.ip_address(first)}/{network.prefixlen}" # IPRange.save() performs arithmetic on the field values before Django's
end_address = f"{ipaddress.ip_address(last)}/{network.prefixlen}" # field conversion runs, so these must be netaddr objects rather than strings.
start_address = netaddr.IPNetwork(f"{ipaddress.ip_address(first)}/{network.prefixlen}")
end_address = netaddr.IPNetwork(f"{ipaddress.ip_address(last)}/{network.prefixlen}")
lookup = { lookup = {
"start_address": start_address, "start_address": start_address,
"end_address": end_address, "end_address": end_address,
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "netbox-better-ips" name = "netbox-better-ips"
version = "1.2.0" version = "1.2.1"
description = "Automatic prefix creation and an organization-aware IP network overview for NetBox 4.6" description = "Automatic prefix creation and an organization-aware IP network overview for NetBox 4.6"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"