fix: skip patchpanel automation on edits
This commit is contained in:
@@ -35,7 +35,7 @@ Release-Tag oder ein bestimmter Commit verwendet werden:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
|
/opt/netbox/venv/bin/pip install --upgrade --force-reinstall \
|
||||||
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.7.3"
|
"git+https://git.mrblake.cc/MrBlake/Netbox-Utilities.git@v0.7.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
|
Alternativ kann hinter dem `@` die vollständige Commit-ID stehen.
|
||||||
@@ -142,15 +142,15 @@ weiter. Auch Kurzformen wie `F01` und `R1` werden als dieselbe Kennung erkannt.
|
|||||||
Fehlt die passende Gegenseite, bleibt der Port unverknüpft; die nachfolgenden
|
Fehlt die passende Gegenseite, bleibt der Port unverknüpft; die nachfolgenden
|
||||||
Nummern rutschen nicht auf.
|
Nummern rutschen nicht auf.
|
||||||
|
|
||||||
Die Zuordnung wird nach Änderungen am Gerät, nach dem Einbau eines Moduls und
|
Die Zuordnung wird ausschließlich beim erstmaligen Anlegen eines Patchpanels,
|
||||||
nach dem Anlegen oder Umbenennen einzelner Front- beziehungsweise Rearports
|
beim Einbau eines neuen Moduls sowie beim Anlegen eines neuen Front- oder
|
||||||
erneut hergestellt. Dabei ersetzt die Patchpanel-Automatik abweichende
|
Rearports hergestellt. Das Bearbeiten eines vorhandenen Patchpanels, Moduls
|
||||||
vorhandene Port-Mappings auf diesen Geräten durch die feste 1:1-Zuordnung.
|
oder Ports löst die Automatik nicht aus.
|
||||||
|
|
||||||
Bei Installation oder Update findet kein automatischer Bestandslauf statt.
|
Bei Installation oder Update findet kein automatischer Bestandslauf statt.
|
||||||
Vorhandene Patchpanel-Geräte und deren Kabelpfade bleiben unverändert. Die
|
Vorhandene Patchpanel-Geräte und deren Kabelpfade bleiben unverändert. Die
|
||||||
Automatik greift erst, wenn ein betreffendes Gerät, Modul oder ein Front-/Rearport
|
Automatik greift erst, wenn ein betreffendes Gerät, Modul oder ein Front-/Rearport
|
||||||
anschließend neu angelegt beziehungsweise gespeichert wird.
|
neu angelegt wird.
|
||||||
|
|
||||||
### Mehrere Geräte mit NetBox Reorder Rack verschieben
|
### Mehrere Geräte mit NetBox Reorder Rack verschieben
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from netbox.plugins import PluginConfig, get_plugin_config
|
from netbox.plugins import PluginConfig, get_plugin_config
|
||||||
|
|
||||||
__version__ = "0.7.3"
|
__version__ = "0.7.4"
|
||||||
|
|
||||||
|
|
||||||
class NetBoxUtilitiesConfig(PluginConfig):
|
class NetBoxUtilitiesConfig(PluginConfig):
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ def synchronize_patchpanel(device_id):
|
|||||||
return len(pairs)
|
return len(pairs)
|
||||||
|
|
||||||
|
|
||||||
def _component_saved(sender, instance, raw=False, **kwargs):
|
def _component_saved(sender, instance, created=False, raw=False, **kwargs):
|
||||||
if not raw and not _component_instantiation_active.get():
|
if created and not raw and not _component_instantiation_active.get():
|
||||||
synchronize_patchpanel(getattr(instance, "device_id", None))
|
synchronize_patchpanel(getattr(instance, "device_id", None))
|
||||||
|
|
||||||
|
|
||||||
@@ -131,6 +131,10 @@ def _wrap_component_container_save(model, device_id_getter):
|
|||||||
|
|
||||||
@wraps(original_save)
|
@wraps(original_save)
|
||||||
def patchpanel_aware_save(instance, *args, **kwargs):
|
def patchpanel_aware_save(instance, *args, **kwargs):
|
||||||
|
created = instance._state.adding
|
||||||
|
if not created:
|
||||||
|
return original_save(instance, *args, **kwargs)
|
||||||
|
|
||||||
token = _component_instantiation_active.set(True)
|
token = _component_instantiation_active.set(True)
|
||||||
try:
|
try:
|
||||||
result = original_save(instance, *args, **kwargs)
|
result = original_save(instance, *args, **kwargs)
|
||||||
|
|||||||
@@ -4,7 +4,14 @@ from unittest.mock import MagicMock, patch
|
|||||||
|
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
|
|
||||||
from netbox_utilities.patchpanel import is_patchpanel, pair_ports, port_identifier, retrace_patchpanel_paths
|
from netbox_utilities.patchpanel import (
|
||||||
|
_component_saved,
|
||||||
|
_wrap_component_container_save,
|
||||||
|
is_patchpanel,
|
||||||
|
pair_ports,
|
||||||
|
port_identifier,
|
||||||
|
retrace_patchpanel_paths,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def port(pk, name):
|
def port(pk, name):
|
||||||
@@ -12,6 +19,41 @@ def port(pk, name):
|
|||||||
|
|
||||||
|
|
||||||
class PatchpanelPairingTest(SimpleTestCase):
|
class PatchpanelPairingTest(SimpleTestCase):
|
||||||
|
@patch("netbox_utilities.patchpanel.synchronize_patchpanel")
|
||||||
|
def test_component_edits_do_not_trigger_automation(self, synchronize):
|
||||||
|
component = SimpleNamespace(device_id=42)
|
||||||
|
|
||||||
|
_component_saved(None, component, created=False)
|
||||||
|
|
||||||
|
synchronize.assert_not_called()
|
||||||
|
|
||||||
|
@patch("netbox_utilities.patchpanel.synchronize_patchpanel")
|
||||||
|
def test_new_components_trigger_automation(self, synchronize):
|
||||||
|
component = SimpleNamespace(device_id=42)
|
||||||
|
|
||||||
|
_component_saved(None, component, created=True)
|
||||||
|
|
||||||
|
synchronize.assert_called_once_with(42)
|
||||||
|
|
||||||
|
@patch("netbox_utilities.patchpanel.synchronize_patchpanel")
|
||||||
|
def test_existing_device_save_does_not_trigger_automation(self, synchronize):
|
||||||
|
class Container:
|
||||||
|
def __init__(self, adding):
|
||||||
|
self._state = SimpleNamespace(adding=adding)
|
||||||
|
self.pk = 42
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self._state.adding = False
|
||||||
|
return "saved"
|
||||||
|
|
||||||
|
_wrap_component_container_save(Container, lambda instance: instance.pk)
|
||||||
|
|
||||||
|
self.assertEqual(Container(adding=False).save(), "saved")
|
||||||
|
synchronize.assert_not_called()
|
||||||
|
|
||||||
|
self.assertEqual(Container(adding=True).save(), "saved")
|
||||||
|
synchronize.assert_called_once_with(42)
|
||||||
|
|
||||||
def test_existing_device_migrations_are_noops(self):
|
def test_existing_device_migrations_are_noops(self):
|
||||||
migration_names = (
|
migration_names = (
|
||||||
"0004_patchpanel_port_mappings",
|
"0004_patchpanel_port_mappings",
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "netbox-utilities"
|
name = "netbox-utilities"
|
||||||
version = "0.7.3"
|
version = "0.7.4"
|
||||||
description = "Navigation, tenant utilities, patchpanel mapping, bulk uploads, and atomic rack reordering for NetBox 4.6"
|
description = "Navigation, tenant utilities, patchpanel mapping, bulk uploads, and atomic rack reordering 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