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:
@@ -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,4 +1,4 @@
|
|||||||
from .config import BetterIPsConfig
|
from .config import BetterIPsConfig
|
||||||
|
|
||||||
__version__ = "1.2.0"
|
__version__ = "1.2.1"
|
||||||
config = BetterIPsConfig
|
config = BetterIPsConfig
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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 = ()
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user