diff --git a/netbox/circuits/migrations/0059_nullify_empty_cable_end.py b/netbox/circuits/migrations/0059_nullify_empty_cable_end.py new file mode 100644 index 000000000..f3ccb758d --- /dev/null +++ b/netbox/circuits/migrations/0059_nullify_empty_cable_end.py @@ -0,0 +1,23 @@ +from django.db import migrations + + +def nullify_empty_cable_end(apps, schema_editor): + """ + Replace empty strings with null values on cached cable end data. Earlier versions + wrote an empty string when a cable termination was deleted, leaving disconnected + terminations inconsistent with those which have never been cabled. + """ + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + db_alias = schema_editor.connection.alias + + CircuitTermination.objects.using(db_alias).filter(cable_end='').update(cable_end=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('circuits', '0058_clear_stale_cable_profile_data'), + ] + + operations = [ + migrations.RunPython(nullify_empty_cable_end, migrations.RunPython.noop), + ] diff --git a/netbox/dcim/migrations/0241_nullify_empty_cable_end.py b/netbox/dcim/migrations/0241_nullify_empty_cable_end.py new file mode 100644 index 000000000..35bab9b52 --- /dev/null +++ b/netbox/dcim/migrations/0241_nullify_empty_cable_end.py @@ -0,0 +1,35 @@ +from django.db import migrations + +CABLED_MODELS = ( + 'ConsolePort', + 'ConsoleServerPort', + 'FrontPort', + 'Interface', + 'PowerFeed', + 'PowerOutlet', + 'PowerPort', + 'RearPort', +) + + +def nullify_empty_cable_end(apps, schema_editor): + """ + Replace empty strings with null values on cached cable end data. Earlier versions + wrote an empty string when a cable termination was deleted, leaving disconnected + endpoints inconsistent with those which have never been cabled. + """ + db_alias = schema_editor.connection.alias + + for model_name in CABLED_MODELS: + model = apps.get_model('dcim', model_name) + model.objects.using(db_alias).filter(cable_end='').update(cable_end=None) + + +class Migration(migrations.Migration): + dependencies = [ + ('dcim', '0240_clear_stale_cable_profile_data'), + ] + + operations = [ + migrations.RunPython(nullify_empty_cable_end, migrations.RunPython.noop), + ] diff --git a/netbox/dcim/signals.py b/netbox/dcim/signals.py index f7fb9c1b4..ca0f12512 100644 --- a/netbox/dcim/signals.py +++ b/netbox/dcim/signals.py @@ -205,7 +205,7 @@ def nullify_connected_endpoints(instance, **kwargs): model = instance.termination_type.model_class() model.objects.filter(pk=instance.termination_id).update( cable=None, - cable_end='', + cable_end=None, cable_connector=None, cable_positions=None, ) diff --git a/netbox/dcim/tests/test_cablepaths.py b/netbox/dcim/tests/test_cablepaths.py index 7fa4f9b8b..d60f5cc86 100644 --- a/netbox/dcim/tests/test_cablepaths.py +++ b/netbox/dcim/tests/test_cablepaths.py @@ -60,11 +60,11 @@ class LegacyCablePathTestCase(BaseCablePathTestCase): interface2.refresh_from_db() self.assertIsNone(interface1.cable_id) - self.assertEqual(interface1.cable_end, '') + self.assertIsNone(interface1.cable_end) self.assertPathIsNotSet(interface1) self.assertIsNone(interface2.cable_id) - self.assertEqual(interface2.cable_end, '') + self.assertIsNone(interface2.cable_end) self.assertPathIsNotSet(interface2) def test_102_consoleport_to_consoleserverport(self): diff --git a/netbox/dcim/tests/test_signals.py b/netbox/dcim/tests/test_signals.py index 99ceff0f0..119b23ecf 100644 --- a/netbox/dcim/tests/test_signals.py +++ b/netbox/dcim/tests/test_signals.py @@ -272,8 +272,8 @@ class CableSignalTestCase(TestCase): self.assertIsNone(interface_b._path_id) self.assertIsNone(interface_a.cable_id) self.assertIsNone(interface_b.cable_id) - self.assertEqual(interface_a.cable_end, '') - self.assertEqual(interface_b.cable_end, '') + self.assertIsNone(interface_a.cable_end) + self.assertIsNone(interface_b.cable_end) def test_deleting_profiled_cable_nullifies_endpoints(self): """ @@ -301,7 +301,7 @@ class CableSignalTestCase(TestCase): for interface in (interface_a, interface_b): interface.refresh_from_db() self.assertIsNone(interface.cable_id) - self.assertEqual(interface.cable_end, '') + self.assertIsNone(interface.cable_end) self.assertIsNone(interface.cable_connector) self.assertIsNone(interface.cable_positions) @@ -367,7 +367,7 @@ class CableSignalTestCase(TestCase): termination.delete() interface_a.refresh_from_db() self.assertIsNone(interface_a.cable_id) - self.assertEqual(interface_a.cable_end, '') + self.assertIsNone(interface_a.cable_end) class MACAddressInterfaceSignalTestCase(TestCase):