0016_replicate_interfaces.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import sys
  2. from django.db import migrations
  3. def replicate_interfaces(apps, schema_editor):
  4. show_output = 'test' not in sys.argv
  5. ContentType = apps.get_model('contenttypes', 'ContentType')
  6. TaggedItem = apps.get_model('extras', 'TaggedItem')
  7. Interface = apps.get_model('dcim', 'Interface')
  8. IPAddress = apps.get_model('ipam', 'IPAddress')
  9. VMInterface = apps.get_model('virtualization', 'VMInterface')
  10. interface_ct = ContentType.objects.get_for_model(Interface)
  11. vminterface_ct = ContentType.objects.get_for_model(VMInterface)
  12. # Replicate dcim.Interface instances assigned to VirtualMachines
  13. original_interfaces = Interface.objects.prefetch_related('tagged_vlans').filter(
  14. virtual_machine__isnull=False
  15. )
  16. interfaces_count = len(original_interfaces)
  17. if show_output:
  18. print(f"\n Replicating {interfaces_count} VM interfaces...", flush=True)
  19. new_interfaces = [
  20. VMInterface(
  21. virtual_machine=interface.virtual_machine,
  22. name=interface.name,
  23. enabled=interface.enabled,
  24. mac_address=interface.mac_address,
  25. mtu=interface.mtu,
  26. mode=interface.mode,
  27. description=interface.description,
  28. untagged_vlan=interface.untagged_vlan,
  29. ) for interface in original_interfaces
  30. ]
  31. VMInterface.objects.bulk_create(new_interfaces, batch_size=1000)
  32. # Pre-fetch the PKs of interfaces with tags/IP addresses
  33. interfaces_with_tags = TaggedItem.objects.filter(
  34. content_type=interface_ct
  35. ).values_list('object_id', flat=True)
  36. interfaces_with_ips = IPAddress.objects.filter(
  37. assigned_object_id__isnull=False
  38. ).values_list('assigned_object_id', flat=True)
  39. if show_output:
  40. print(f" Replicating assigned objects...", flush=True)
  41. for i, interface in enumerate(original_interfaces):
  42. vminterface = new_interfaces[i]
  43. # Copy tagged VLANs
  44. if interface.tagged_vlans.exists():
  45. vminterface.tagged_vlans.set(interface.tagged_vlans.all())
  46. # Reassign tags to the new instance
  47. if interface.pk in interfaces_with_tags:
  48. TaggedItem.objects.filter(content_type=interface_ct, object_id=interface.pk).update(
  49. content_type=vminterface_ct,
  50. object_id=vminterface.pk
  51. )
  52. # Update any assigned IPAddresses
  53. if interface.pk in interfaces_with_ips:
  54. IPAddress.objects.filter(assigned_object_type=interface_ct, assigned_object_id=interface.pk).update(
  55. assigned_object_type=vminterface_ct,
  56. assigned_object_id=vminterface.pk
  57. )
  58. # Progress counter
  59. if show_output and not i % 1000:
  60. percentage = int(i / interfaces_count * 100)
  61. print(f" {i}/{interfaces_count} ({percentage}%)", flush=True)
  62. # Verify that all interfaces have been replicated
  63. replicated_count = VMInterface.objects.count()
  64. assert replicated_count == original_interfaces.count(), "Replicated interfaces count does not match original count!"
  65. # Delete all interfaces not assigned to a Device
  66. Interface.objects.filter(device__isnull=True).delete()
  67. class Migration(migrations.Migration):
  68. dependencies = [
  69. ('ipam', '0037_ipaddress_assignment'),
  70. ('virtualization', '0015_vminterface'),
  71. ]
  72. operations = [
  73. migrations.RunPython(
  74. code=replicate_interfaces
  75. ),
  76. ]