Closes #19627: Object change migrators (#19628)

* Initial work on ObjectChange data migrations

* Fix migration bug

* Add migrators for MAC address assignments

* Update reverting kwarg; allow pop() to fail

* Cross-reference MAC address migrators

* Split migrator logic across migrations

* Add missing migrator
This commit is contained in:
Jeremy Stretch
2025-06-05 11:47:59 -04:00
committed by GitHub
parent bd8cf64ded
commit 179c06ec20
13 changed files with 261 additions and 1 deletions

View File

@@ -1,4 +1,5 @@
import django.db.models.deletion
from django.contrib.contenttypes.models import ContentType
from django.db import migrations, models
@@ -44,3 +45,20 @@ class Migration(migrations.Migration):
# Copy over existing site assignments
migrations.RunPython(code=copy_site_assignments, reverse_code=migrations.RunPython.noop),
]
def oc_prefix_scope(objectchange, reverting):
site_ct = ContentType.objects.get_by_natural_key('dcim', 'site').pk
for data in (objectchange.prechange_data, objectchange.postchange_data):
if data is None:
continue
if site_id := data.get('site'):
data.update({
'scope_type': site_ct,
'scope_id': site_id,
})
objectchange_migrators = {
'ipam.prefix': oc_prefix_scope,
}

View File

@@ -60,3 +60,14 @@ class Migration(migrations.Migration):
name='site',
),
]
def oc_prefix_remove_fields(objectchange, reverting):
for data in (objectchange.prechange_data, objectchange.postchange_data):
if data is not None:
data.pop('site', None)
objectchange_migrators = {
'ipam.prefix': oc_prefix_remove_fields,
}

View File

@@ -1,3 +1,4 @@
from django.contrib.contenttypes.models import ContentType
from django.db import migrations
from django.db.models import F
@@ -54,3 +55,26 @@ class Migration(migrations.Migration):
reverse_code=repopulate_device_and_virtualmachine_relations,
)
]
def oc_service_parent(objectchange, reverting):
device_ct = ContentType.objects.get_by_natural_key('dcim', 'device').pk
virtual_machine_ct = ContentType.objects.get_by_natural_key('virtualization', 'virtualmachine').pk
for data in (objectchange.prechange_data, objectchange.postchange_data):
if data is None:
continue
if device_id := data.get('device'):
data.update({
'parent_object_type': device_ct,
'parent_object_id': device_id,
})
elif virtual_machine_id := data.get('virtual_machine'):
data.update({
'parent_object_type': virtual_machine_ct,
'parent_object_id': virtual_machine_id,
})
objectchange_migrators = {
'ipam.service': oc_service_parent,
}

View File

@@ -37,3 +37,15 @@ class Migration(migrations.Migration):
),
),
]
def oc_service_remove_fields(objectchange, reverting):
for data in (objectchange.prechange_data, objectchange.postchange_data):
if data is not None:
data.pop('device', None)
data.pop('virtual_machine', None)
objectchange_migrators = {
'ipam.service': oc_service_remove_fields,
}