Jeremy Stretch 2 лет назад
Родитель
Сommit
b554e70eda
100 измененных файлов с 2511 добавлено и 4001 удалено
  1. 0 20
      netbox/circuits/migrations/0003_extend_tag_support.py
  2. 127 0
      netbox/circuits/migrations/0003_squashed_0037.py
  3. 0 21
      netbox/circuits/migrations/0004_rename_cable_peer.py
  4. 0 17
      netbox/circuits/migrations/0032_provider_service_id.py
  5. 0 44
      netbox/circuits/migrations/0033_standardize_id_fields.py
  6. 0 38
      netbox/circuits/migrations/0034_created_datetimefield.py
  7. 0 19
      netbox/circuits/migrations/0035_provider_asns.py
  8. 0 28
      netbox/circuits/migrations/0036_circuit_termination_date_tags_custom_fields.py
  9. 0 16
      netbox/circuits/migrations/0037_new_cabling_models.py
  10. 0 20
      netbox/circuits/migrations/0038_cabling_cleanup.py
  11. 70 36
      netbox/circuits/migrations/0038_squashed_0042.py
  12. 0 39
      netbox/circuits/migrations/0039_unique_constraints.py
  13. 0 59
      netbox/circuits/migrations/0040_provider_remove_deprecated_fields.py
  14. 0 18
      netbox/circuits/migrations/0041_standardize_description_comments.py
  15. 65 9
      netbox/core/migrations/0001_squashed_0005.py
  16. 0 40
      netbox/core/migrations/0002_managedfile.py
  17. 0 39
      netbox/core/migrations/0003_job.py
  18. 0 46
      netbox/core/migrations/0004_replicate_jobresults.py
  19. 0 18
      netbox/core/migrations/0005_job_created_auto_now.py
  20. 0 21
      netbox/dcim/migrations/0131_consoleport_speed.py
  21. 1194 0
      netbox/dcim/migrations/0131_squashed_0159.py
  22. 0 16
      netbox/dcim/migrations/0132_cable_length.py
  23. 0 32
      netbox/dcim/migrations/0133_port_colors.py
  24. 0 23
      netbox/dcim/migrations/0134_interface_wwn_bridge.py
  25. 0 23
      netbox/dcim/migrations/0135_tenancy_extensions.py
  26. 0 21
      netbox/dcim/migrations/0136_device_airflow.py
  27. 0 83
      netbox/dcim/migrations/0137_relax_uniqueness_constraints.py
  28. 0 50
      netbox/dcim/migrations/0138_extend_tag_support.py
  29. 0 91
      netbox/dcim/migrations/0139_rename_cable_peer.py
  30. 0 49
      netbox/dcim/migrations/0140_wireless.py
  31. 0 19
      netbox/dcim/migrations/0141_asn_model.py
  32. 0 29
      netbox/dcim/migrations/0142_rename_128gfc_qsfp28.py
  33. 0 23
      netbox/dcim/migrations/0143_remove_primary_for_related_name.py
  34. 0 31
      netbox/dcim/migrations/0144_fix_cable_abs_length.py
  35. 0 59
      netbox/dcim/migrations/0145_site_remove_deprecated_fields.py
  36. 0 279
      netbox/dcim/migrations/0146_modules.py
  37. 0 38
      netbox/dcim/migrations/0147_inventoryitemrole.py
  38. 0 23
      netbox/dcim/migrations/0148_inventoryitem_component.py
  39. 0 43
      netbox/dcim/migrations/0149_inventoryitem_templates.py
  40. 0 20
      netbox/dcim/migrations/0150_interface_vrf.py
  41. 0 23
      netbox/dcim/migrations/0151_interface_speed_duplex.py
  42. 0 274
      netbox/dcim/migrations/0152_standardize_id_fields.py
  43. 0 208
      netbox/dcim/migrations/0153_created_datetimefield.py
  44. 0 23
      netbox/dcim/migrations/0154_half_height_rack_units.py
  45. 0 33
      netbox/dcim/migrations/0155_interface_poe_mode_type.py
  46. 0 18
      netbox/dcim/migrations/0156_location_status.py
  47. 0 95
      netbox/dcim/migrations/0157_new_cabling_models.py
  48. 0 87
      netbox/dcim/migrations/0158_populate_cable_terminations.py
  49. 0 50
      netbox/dcim/migrations/0159_populate_cable_paths.py
  50. 0 46
      netbox/dcim/migrations/0160_populate_cable_ends.py
  51. 294 2
      netbox/dcim/migrations/0160_squashed_0166.py
  52. 0 134
      netbox/dcim/migrations/0161_cabling_cleanup.py
  53. 0 72
      netbox/dcim/migrations/0163_weight_fields.py
  54. 0 18
      netbox/dcim/migrations/0164_rack_mounting_depth.py
  55. 0 78
      netbox/dcim/migrations/0165_standardize_description_comments.py
  56. 0 54
      netbox/dcim/migrations/0166_virtualdevicecontext.py
  57. 0 18
      netbox/dcim/migrations/0167_module_status.py
  58. 251 0
      netbox/dcim/migrations/0167_squashed_0182.py
  59. 0 22
      netbox/dcim/migrations/0168_interface_template_enabled.py
  60. 0 19
      netbox/dcim/migrations/0169_devicetype_default_platform.py
  61. 0 28
      netbox/dcim/migrations/0170_configtemplate.py
  62. 0 21
      netbox/dcim/migrations/0171_cabletermination_change_logging.py
  63. 0 42
      netbox/dcim/migrations/0172_larger_power_draw_values.py
  64. 0 19
      netbox/dcim/migrations/0173_remove_napalm_fields.py
  65. 0 22
      netbox/dcim/migrations/0174_device_latitude_device_longitude.py
  66. 0 18
      netbox/dcim/migrations/0174_rack_starting_unit.py
  67. 0 25
      netbox/dcim/migrations/0175_device_oob_ip.py
  68. 0 83
      netbox/dcim/migrations/0176_device_component_counters.py
  69. 0 83
      netbox/dcim/migrations/0177_devicetype_component_counters.py
  70. 0 31
      netbox/dcim/migrations/0178_virtual_chassis_member_counter.py
  71. 0 18
      netbox/dcim/migrations/0179_interfacetemplate_rf_role.py
  72. 0 20
      netbox/dcim/migrations/0180_powerfeed_tenant.py
  73. 0 35
      netbox/dcim/migrations/0181_rename_device_role_device_role.py
  74. 0 22
      netbox/dcim/migrations/0182_zero_length_cable_fix.py
  75. 0 16
      netbox/extras/migrations/0060_customlink_button_class.py
  76. 510 0
      netbox/extras/migrations/0060_squashed_0086.py
  77. 0 51
      netbox/extras/migrations/0061_extras_change_logging.py
  78. 0 26
      netbox/extras/migrations/0062_clear_secrets_changelog.py
  79. 0 18
      netbox/extras/migrations/0063_webhook_conditions.py
  80. 0 20
      netbox/extras/migrations/0064_configrevision.py
  81. 0 16
      netbox/extras/migrations/0065_imageattachment_change_logging.py
  82. 0 34
      netbox/extras/migrations/0066_customfield_name_validation.py
  83. 0 21
      netbox/extras/migrations/0067_customfield_min_max_values.py
  84. 0 18
      netbox/extras/migrations/0068_configcontext_cluster_types.py
  85. 0 18
      netbox/extras/migrations/0069_custom_object_field.py
  86. 0 18
      netbox/extras/migrations/0070_customlink_enabled.py
  87. 0 89
      netbox/extras/migrations/0071_standardize_id_fields.py
  88. 0 53
      netbox/extras/migrations/0072_created_datetimefield.py
  89. 0 23
      netbox/extras/migrations/0073_journalentry_tags_custom_fields.py
  90. 0 27
      netbox/extras/migrations/0074_customfield_extensions.py
  91. 0 19
      netbox/extras/migrations/0075_configcontext_locations.py
  92. 0 18
      netbox/extras/migrations/0076_tag_slug_unicode.py
  93. 0 21
      netbox/extras/migrations/0077_customlink_extend_text_and_url.py
  94. 0 27
      netbox/extras/migrations/0078_unique_constraints.py
  95. 0 31
      netbox/extras/migrations/0079_scheduled_jobs.py
  96. 0 32
      netbox/extras/migrations/0080_customlink_content_types.py
  97. 0 40
      netbox/extras/migrations/0081_exporttemplate_content_types.py
  98. 0 35
      netbox/extras/migrations/0082_savedfilter.py
  99. 0 44
      netbox/extras/migrations/0083_search.py
  100. 0 45
      netbox/extras/migrations/0084_staging.py

+ 0 - 20
netbox/circuits/migrations/0003_extend_tag_support.py

@@ -1,20 +0,0 @@
-# Generated by Django 3.2.8 on 2021-10-21 14:50
-
-from django.db import migrations
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0062_clear_secrets_changelog'),
-        ('circuits', '0002_squashed_0029'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='circuittype',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-    ]

+ 127 - 0
netbox/circuits/migrations/0003_squashed_0037.py

@@ -0,0 +1,127 @@
+import taggit.managers
+from django.db import migrations, models
+
+import utilities.json
+
+
+class Migration(migrations.Migration):
+
+    replaces = [
+        ('circuits', '0003_extend_tag_support'),
+        ('circuits', '0004_rename_cable_peer'),
+        ('circuits', '0032_provider_service_id'),
+        ('circuits', '0033_standardize_id_fields'),
+        ('circuits', '0034_created_datetimefield'),
+        ('circuits', '0035_provider_asns'),
+        ('circuits', '0036_circuit_termination_date_tags_custom_fields'),
+        ('circuits', '0037_new_cabling_models')
+    ]
+
+    dependencies = [
+        ('ipam', '0047_squashed_0053'),
+        ('extras', '0002_squashed_0059'),
+        ('circuits', '0002_squashed_0029'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='circuittype',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.RenameField(
+            model_name='circuittermination',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='circuittermination',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.AddField(
+            model_name='providernetwork',
+            name='service_id',
+            field=models.CharField(blank=True, max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='circuit',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='circuittermination',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='circuittype',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='provider',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='providernetwork',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='circuittermination',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='circuit',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='circuittermination',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='circuittype',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='provider',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='providernetwork',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='provider',
+            name='asns',
+            field=models.ManyToManyField(blank=True, related_name='providers', to='ipam.asn'),
+        ),
+        migrations.AddField(
+            model_name='circuit',
+            name='termination_date',
+            field=models.DateField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='circuittermination',
+            name='custom_field_data',
+            field=models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
+        ),
+        migrations.AddField(
+            model_name='circuittermination',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='circuittermination',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+    ]

+ 0 - 21
netbox/circuits/migrations/0004_rename_cable_peer.py

@@ -1,21 +0,0 @@
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0003_extend_tag_support'),
-    ]
-
-    operations = [
-        migrations.RenameField(
-            model_name='circuittermination',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='circuittermination',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-    ]

+ 0 - 17
netbox/circuits/migrations/0032_provider_service_id.py

@@ -1,17 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0004_rename_cable_peer'),
-        ('dcim', '0145_site_remove_deprecated_fields'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='providernetwork',
-            name='service_id',
-            field=models.CharField(blank=True, max_length=100),
-        ),
-    ]

+ 0 - 44
netbox/circuits/migrations/0033_standardize_id_fields.py

@@ -1,44 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0032_provider_service_id'),
-    ]
-
-    operations = [
-        # Model IDs
-        migrations.AlterField(
-            model_name='circuit',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='circuittermination',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='circuittype',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='provider',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='providernetwork',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-
-        # GFK IDs
-        migrations.AlterField(
-            model_name='circuittermination',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 38
netbox/circuits/migrations/0034_created_datetimefield.py

@@ -1,38 +0,0 @@
-# Generated by Django 4.0.2 on 2022-02-08 18:54
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0033_standardize_id_fields'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='circuit',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='circuittermination',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='circuittype',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='provider',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='providernetwork',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-    ]

+ 0 - 19
netbox/circuits/migrations/0035_provider_asns.py

@@ -1,19 +0,0 @@
-# Generated by Django 4.0.3 on 2022-03-30 20:27
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('ipam', '0057_created_datetimefield'),
-        ('circuits', '0034_created_datetimefield'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='provider',
-            name='asns',
-            field=models.ManyToManyField(blank=True, related_name='providers', to='ipam.asn'),
-        ),
-    ]

+ 0 - 28
netbox/circuits/migrations/0036_circuit_termination_date_tags_custom_fields.py

@@ -1,28 +0,0 @@
-from utilities.json import CustomFieldJSONEncoder
-from django.db import migrations, models
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0035_provider_asns'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='circuit',
-            name='termination_date',
-            field=models.DateField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='circuittermination',
-            name='custom_field_data',
-            field=models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder),
-        ),
-        migrations.AddField(
-            model_name='circuittermination',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-    ]

+ 0 - 16
netbox/circuits/migrations/0037_new_cabling_models.py

@@ -1,16 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0036_circuit_termination_date_tags_custom_fields'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='circuittermination',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-    ]

+ 0 - 20
netbox/circuits/migrations/0038_cabling_cleanup.py

@@ -1,20 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0037_new_cabling_models'),
-        ('dcim', '0160_populate_cable_ends'),
-    ]
-
-    operations = [
-        migrations.RemoveField(
-            model_name='circuittermination',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='circuittermination',
-            name='_link_peer_type',
-        ),
-    ]

+ 70 - 36
netbox/circuits/migrations/0042_provideraccount.py → netbox/circuits/migrations/0038_squashed_0042.py

@@ -1,46 +1,83 @@
-from django.db import migrations, models
 import django.db.models.deletion
 import taggit.managers
-import utilities.json
-
-
-def create_provideraccounts_from_providers(apps, schema_editor):
-    """
-    Migrate Account in Provider model to separate account model
-    """
-    Provider = apps.get_model('circuits', 'Provider')
-    ProviderAccount = apps.get_model('circuits', 'ProviderAccount')
-
-    provider_accounts = []
-    for provider in Provider.objects.all():
-        if provider.account:
-            provider_accounts.append(ProviderAccount(
-                provider=provider,
-                account=provider.account
-            ))
-    ProviderAccount.objects.bulk_create(provider_accounts, batch_size=100)
-
+from django.db import migrations, models
 
-def restore_providers_from_provideraccounts(apps, schema_editor):
-    """
-    Restore Provider account values from auto-generated ProviderAccounts
-    """
-    ProviderAccount = apps.get_model('circuits', 'ProviderAccount')
-    provider_accounts = ProviderAccount.objects.order_by('pk')
-    for provideraccount in provider_accounts:
-        if provider_accounts.filter(provider=provideraccount.provider)[0] == provideraccount:
-            provideraccount.provider.account = provideraccount.account
-            provideraccount.provider.save()
+import utilities.json
 
 
 class Migration(migrations.Migration):
 
-    dependencies = [
-        ('extras', '0084_staging'),
+    replaces = [
+        ('circuits', '0038_cabling_cleanup'),
+        ('circuits', '0039_unique_constraints'),
+        ('circuits', '0040_provider_remove_deprecated_fields'),
         ('circuits', '0041_standardize_description_comments'),
+        ('circuits', '0042_provideraccount')
+    ]
+
+    dependencies = [
+        ('circuits', '0037_new_cabling_models'),
+        ('dcim', '0160_populate_cable_ends'),
     ]
 
     operations = [
+        migrations.RemoveField(
+            model_name='circuittermination',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='circuittermination',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveConstraint(
+            model_name='providernetwork',
+            name='circuits_providernetwork_provider_name',
+        ),
+        migrations.AlterUniqueTogether(
+            name='circuit',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='circuittermination',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='providernetwork',
+            unique_together=set(),
+        ),
+        migrations.AddConstraint(
+            model_name='circuit',
+            constraint=models.UniqueConstraint(fields=('provider', 'cid'), name='circuits_circuit_unique_provider_cid'),
+        ),
+        migrations.AddConstraint(
+            model_name='circuittermination',
+            constraint=models.UniqueConstraint(fields=('circuit', 'term_side'), name='circuits_circuittermination_unique_circuit_term_side'),
+        ),
+        migrations.AddConstraint(
+            model_name='providernetwork',
+            constraint=models.UniqueConstraint(fields=('provider', 'name'), name='circuits_providernetwork_unique_provider_name'),
+        ),
+        migrations.RemoveField(
+            model_name='provider',
+            name='admin_contact',
+        ),
+        migrations.RemoveField(
+            model_name='provider',
+            name='asn',
+        ),
+        migrations.RemoveField(
+            model_name='provider',
+            name='noc_contact',
+        ),
+        migrations.RemoveField(
+            model_name='provider',
+            name='portal_url',
+        ),
+        migrations.AddField(
+            model_name='provider',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
         migrations.CreateModel(
             name='ProviderAccount',
             fields=[
@@ -67,9 +104,6 @@ class Migration(migrations.Migration):
             model_name='provideraccount',
             constraint=models.UniqueConstraint(fields=('provider', 'account'), name='circuits_provideraccount_unique_provider_account'),
         ),
-        migrations.RunPython(
-            create_provideraccounts_from_providers, restore_providers_from_provideraccounts
-        ),
         migrations.RemoveField(
             model_name='provider',
             name='account',
@@ -77,7 +111,7 @@ class Migration(migrations.Migration):
         migrations.AddField(
             model_name='circuit',
             name='provider_account',
-            field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.provideraccount', null=True, blank=True),
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.provideraccount'),
             preserve_default=False,
         ),
         migrations.AlterModelOptions(

+ 0 - 39
netbox/circuits/migrations/0039_unique_constraints.py

@@ -1,39 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0038_cabling_cleanup'),
-    ]
-
-    operations = [
-        migrations.RemoveConstraint(
-            model_name='providernetwork',
-            name='circuits_providernetwork_provider_name',
-        ),
-        migrations.AlterUniqueTogether(
-            name='circuit',
-            unique_together=set(),
-        ),
-        migrations.AlterUniqueTogether(
-            name='circuittermination',
-            unique_together=set(),
-        ),
-        migrations.AlterUniqueTogether(
-            name='providernetwork',
-            unique_together=set(),
-        ),
-        migrations.AddConstraint(
-            model_name='circuit',
-            constraint=models.UniqueConstraint(fields=('provider', 'cid'), name='circuits_circuit_unique_provider_cid'),
-        ),
-        migrations.AddConstraint(
-            model_name='circuittermination',
-            constraint=models.UniqueConstraint(fields=('circuit', 'term_side'), name='circuits_circuittermination_unique_circuit_term_side'),
-        ),
-        migrations.AddConstraint(
-            model_name='providernetwork',
-            constraint=models.UniqueConstraint(fields=('provider', 'name'), name='circuits_providernetwork_unique_provider_name'),
-        ),
-    ]

+ 0 - 59
netbox/circuits/migrations/0040_provider_remove_deprecated_fields.py

@@ -1,59 +0,0 @@
-import os
-
-from django.db import migrations
-from django.db.utils import DataError
-
-
-def check_legacy_data(apps, schema_editor):
-    """
-    Abort the migration if any legacy provider fields still contain data.
-    """
-    Provider = apps.get_model('circuits', 'Provider')
-
-    provider_count = Provider.objects.exclude(asn__isnull=True).count()
-    if provider_count and 'NETBOX_DELETE_LEGACY_DATA' not in os.environ:
-        raise DataError(
-            f"Unable to proceed with deleting asn field from Provider model: Found {provider_count} "
-            f"providers with legacy ASN data. Please ensure all legacy provider ASN data has been "
-            f"migrated to ASN objects before proceeding. Or, set the NETBOX_DELETE_LEGACY_DATA "
-            f"environment variable to bypass this safeguard and delete all legacy provider ASN data."
-        )
-
-    provider_count = Provider.objects.exclude(admin_contact='', noc_contact='', portal_url='').count()
-    if provider_count and 'NETBOX_DELETE_LEGACY_DATA' not in os.environ:
-        raise DataError(
-            f"Unable to proceed with deleting contact fields from Provider model: Found {provider_count} "
-            f"providers with legacy contact data. Please ensure all legacy provider contact data has been "
-            f"migrated to contact objects before proceeding. Or, set the NETBOX_DELETE_LEGACY_DATA "
-            f"environment variable to bypass this safeguard and delete all legacy provider contact data."
-        )
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0039_unique_constraints'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=check_legacy_data,
-            reverse_code=migrations.RunPython.noop
-        ),
-        migrations.RemoveField(
-            model_name='provider',
-            name='admin_contact',
-        ),
-        migrations.RemoveField(
-            model_name='provider',
-            name='asn',
-        ),
-        migrations.RemoveField(
-            model_name='provider',
-            name='noc_contact',
-        ),
-        migrations.RemoveField(
-            model_name='provider',
-            name='portal_url',
-        ),
-    ]

+ 0 - 18
netbox/circuits/migrations/0041_standardize_description_comments.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.1.2 on 2022-11-03 18:24
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0040_provider_remove_deprecated_fields'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='provider',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-    ]

+ 65 - 9
netbox/core/migrations/0001_initial.py → netbox/core/migrations/0001_squashed_0005.py

@@ -1,18 +1,26 @@
-# Generated by Django 4.1.5 on 2023-02-02 02:37
-
 import django.core.validators
-from django.db import migrations, models
 import django.db.models.deletion
 import taggit.managers
+from django.conf import settings
+from django.db import migrations, models
+
 import utilities.json
 
 
 class Migration(migrations.Migration):
 
-    initial = True
+    replaces = [
+        ('core', '0001_initial'),
+        ('core', '0002_managedfile'),
+        ('core', '0003_job'),
+        ('core', '0004_replicate_jobresults'),
+        ('core', '0005_job_created_auto_now')
+    ]
 
     dependencies = [
-        ('extras', '0084_staging'),
+        ('contenttypes', '0002_remove_content_type_name'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('extras', '0002_squashed_0059'),
     ]
 
     operations = [
@@ -71,13 +79,61 @@ class Migration(migrations.Migration):
                 ('datafile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='core.datafile')),
                 ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
             ],
-        ),
-        migrations.AddIndex(
-            model_name='autosyncrecord',
-            index=models.Index(fields=['object_type', 'object_id'], name='core_autosy_object__c17bac_idx'),
+            options={
+                'indexes': [models.Index(fields=['object_type', 'object_id'], name='core_autosy_object__c17bac_idx')],
+            },
         ),
         migrations.AddConstraint(
             model_name='autosyncrecord',
             constraint=models.UniqueConstraint(fields=('object_type', 'object_id'), name='core_autosyncrecord_object'),
         ),
+        migrations.CreateModel(
+            name='ManagedFile',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('data_path', models.CharField(blank=True, editable=False, max_length=1000)),
+                ('data_synced', models.DateTimeField(blank=True, editable=False, null=True)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('last_updated', models.DateTimeField(blank=True, editable=False, null=True)),
+                ('file_root', models.CharField(max_length=1000)),
+                ('file_path', models.FilePathField(editable=False)),
+                ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')),
+                ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')),
+                ('auto_sync_enabled', models.BooleanField(default=False)),
+            ],
+            options={
+                'ordering': ('file_root', 'file_path'),
+                'indexes': [models.Index(fields=['file_root', 'file_path'], name='core_managedfile_root_path')],
+            },
+        ),
+        migrations.AddConstraint(
+            model_name='managedfile',
+            constraint=models.UniqueConstraint(fields=('file_root', 'file_path'), name='core_managedfile_unique_root_path'),
+        ),
+        migrations.CreateModel(
+            name='Job',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('object_id', models.PositiveBigIntegerField(blank=True, null=True)),
+                ('name', models.CharField(max_length=200)),
+                ('created', models.DateTimeField()),
+                ('scheduled', models.DateTimeField(blank=True, null=True)),
+                ('interval', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])),
+                ('started', models.DateTimeField(blank=True, null=True)),
+                ('completed', models.DateTimeField(blank=True, null=True)),
+                ('status', models.CharField(default='pending', max_length=30)),
+                ('data', models.JSONField(blank=True, null=True)),
+                ('job_id', models.UUIDField(unique=True)),
+                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='jobs', to='contenttypes.contenttype')),
+                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'ordering': ['-created'],
+            },
+        ),
+        migrations.AlterField(
+            model_name='job',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True),
+        ),
     ]

+ 0 - 40
netbox/core/migrations/0002_managedfile.py

@@ -1,40 +0,0 @@
-# Generated by Django 4.1.7 on 2023-03-23 17:35
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='ManagedFile',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('data_path', models.CharField(blank=True, editable=False, max_length=1000)),
-                ('data_synced', models.DateTimeField(blank=True, editable=False, null=True)),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('last_updated', models.DateTimeField(blank=True, editable=False, null=True)),
-                ('file_root', models.CharField(max_length=1000)),
-                ('file_path', models.FilePathField(editable=False)),
-                ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')),
-                ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')),
-                ('auto_sync_enabled', models.BooleanField(default=False)),
-            ],
-            options={
-                'ordering': ('file_root', 'file_path'),
-            },
-        ),
-        migrations.AddIndex(
-            model_name='managedfile',
-            index=models.Index(fields=['file_root', 'file_path'], name='core_managedfile_root_path'),
-        ),
-        migrations.AddConstraint(
-            model_name='managedfile',
-            constraint=models.UniqueConstraint(fields=('file_root', 'file_path'), name='core_managedfile_unique_root_path'),
-        ),
-    ]

+ 0 - 39
netbox/core/migrations/0003_job.py

@@ -1,39 +0,0 @@
-# Generated by Django 4.1.7 on 2023-03-27 15:02
-
-from django.conf import settings
-import django.core.validators
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('core', '0002_managedfile'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Job',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('object_id', models.PositiveBigIntegerField(blank=True, null=True)),
-                ('name', models.CharField(max_length=200)),
-                ('created', models.DateTimeField()),
-                ('scheduled', models.DateTimeField(blank=True, null=True)),
-                ('interval', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)])),
-                ('started', models.DateTimeField(blank=True, null=True)),
-                ('completed', models.DateTimeField(blank=True, null=True)),
-                ('status', models.CharField(default='pending', max_length=30)),
-                ('data', models.JSONField(blank=True, null=True)),
-                ('job_id', models.UUIDField(unique=True)),
-                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='jobs', to='contenttypes.contenttype')),
-                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'ordering': ['-created'],
-            },
-        ),
-    ]

+ 0 - 46
netbox/core/migrations/0004_replicate_jobresults.py

@@ -1,46 +0,0 @@
-from django.db import migrations
-
-
-def replicate_jobresults(apps, schema_editor):
-    """
-    Replicate existing JobResults to the new Jobs table before deleting the old JobResults table.
-    """
-    Job = apps.get_model('core', 'Job')
-    JobResult = apps.get_model('extras', 'JobResult')
-
-    jobs = []
-    for job_result in JobResult.objects.order_by('pk').iterator(chunk_size=100):
-        jobs.append(
-            Job(
-                object_type=job_result.obj_type,
-                name=job_result.name,
-                created=job_result.created,
-                scheduled=job_result.scheduled,
-                interval=job_result.interval,
-                started=job_result.started,
-                completed=job_result.completed,
-                user=job_result.user,
-                status=job_result.status,
-                data=job_result.data,
-                job_id=job_result.job_id,
-            )
-        )
-        if len(jobs) == 100:
-            Job.objects.bulk_create(jobs)
-            jobs = []
-    if jobs:
-        Job.objects.bulk_create(jobs)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0003_job'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=replicate_jobresults,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 18
netbox/core/migrations/0005_job_created_auto_now.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.1.7 on 2023-03-27 17:28
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('core', '0004_replicate_jobresults'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='job',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True),
-        ),
-    ]

+ 0 - 21
netbox/dcim/migrations/0131_consoleport_speed.py

@@ -1,21 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0130_sitegroup'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='consoleport',
-            name='speed',
-            field=models.PositiveIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverport',
-            name='speed',
-            field=models.PositiveIntegerField(blank=True, null=True),
-        ),
-    ]

+ 1194 - 0
netbox/dcim/migrations/0131_squashed_0159.py

@@ -0,0 +1,1194 @@
+import dcim.fields
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import mptt.fields
+import taggit.managers
+import utilities.fields
+import utilities.json
+import utilities.ordering
+
+
+class Migration(migrations.Migration):
+
+    replaces = [
+        ('dcim', '0131_consoleport_speed'),
+        ('dcim', '0132_cable_length'),
+        ('dcim', '0133_port_colors'),
+        ('dcim', '0134_interface_wwn_bridge'),
+        ('dcim', '0135_tenancy_extensions'),
+        ('dcim', '0136_device_airflow'),
+        ('dcim', '0137_relax_uniqueness_constraints'),
+        ('dcim', '0138_extend_tag_support'),
+        ('dcim', '0139_rename_cable_peer'),
+        ('dcim', '0140_wireless'),
+        ('dcim', '0141_asn_model'),
+        ('dcim', '0142_rename_128gfc_qsfp28'),
+        ('dcim', '0143_remove_primary_for_related_name'),
+        ('dcim', '0144_fix_cable_abs_length'),
+        ('dcim', '0145_site_remove_deprecated_fields'),
+        ('dcim', '0146_modules'),
+        ('dcim', '0147_inventoryitemrole'),
+        ('dcim', '0148_inventoryitem_component'),
+        ('dcim', '0149_inventoryitem_templates'),
+        ('dcim', '0150_interface_vrf'),
+        ('dcim', '0151_interface_speed_duplex'),
+        ('dcim', '0152_standardize_id_fields'),
+        ('dcim', '0153_created_datetimefield'),
+        ('dcim', '0154_half_height_rack_units'),
+        ('dcim', '0155_interface_poe_mode_type'),
+        ('dcim', '0156_location_status'),
+        ('dcim', '0157_new_cabling_models'),
+        ('dcim', '0158_populate_cable_terminations'),
+        ('dcim', '0159_populate_cable_paths')
+    ]
+
+    dependencies = [
+        ('tenancy', '0012_standardize_models'),
+        ('extras', '0002_squashed_0059'),
+        ('dcim', '0130_sitegroup'),
+        ('contenttypes', '0002_remove_content_type_name'),
+        ('ipam', '0053_asn_model'),
+        ('wireless', '0001_wireless'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='consoleport',
+            name='speed',
+            field=models.PositiveIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverport',
+            name='speed',
+            field=models.PositiveIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='cable',
+            name='length',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
+        ),
+        migrations.AddField(
+            model_name='frontport',
+            name='color',
+            field=utilities.fields.ColorField(blank=True, max_length=6),
+        ),
+        migrations.AddField(
+            model_name='frontporttemplate',
+            name='color',
+            field=utilities.fields.ColorField(blank=True, max_length=6),
+        ),
+        migrations.AddField(
+            model_name='rearport',
+            name='color',
+            field=utilities.fields.ColorField(blank=True, max_length=6),
+        ),
+        migrations.AddField(
+            model_name='rearporttemplate',
+            name='color',
+            field=utilities.fields.ColorField(blank=True, max_length=6),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='wwn',
+            field=dcim.fields.WWNField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='bridge',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interface'),
+        ),
+        migrations.AddField(
+            model_name='location',
+            name='tenant',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='locations', to='tenancy.tenant'),
+        ),
+        migrations.AddField(
+            model_name='cable',
+            name='tenant',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='cables', to='tenancy.tenant'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='airflow',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='airflow',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AlterField(
+            model_name='region',
+            name='name',
+            field=models.CharField(max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='region',
+            name='slug',
+            field=models.SlugField(max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='sitegroup',
+            name='name',
+            field=models.CharField(max_length=100),
+        ),
+        migrations.AlterField(
+            model_name='sitegroup',
+            name='slug',
+            field=models.SlugField(max_length=100),
+        ),
+        migrations.AlterUniqueTogether(
+            name='location',
+            unique_together=set(),
+        ),
+        migrations.AddConstraint(
+            model_name='location',
+            constraint=models.UniqueConstraint(fields=('site', 'parent', 'name'), name='dcim_location_parent_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='location',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'name'), name='dcim_location_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='location',
+            constraint=models.UniqueConstraint(fields=('site', 'parent', 'slug'), name='dcim_location_parent_slug'),
+        ),
+        migrations.AddConstraint(
+            model_name='location',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'slug'), name='dcim_location_slug'),
+        ),
+        migrations.AddConstraint(
+            model_name='region',
+            constraint=models.UniqueConstraint(fields=('parent', 'name'), name='dcim_region_parent_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='region',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_region_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='region',
+            constraint=models.UniqueConstraint(fields=('parent', 'slug'), name='dcim_region_parent_slug'),
+        ),
+        migrations.AddConstraint(
+            model_name='region',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_region_slug'),
+        ),
+        migrations.AddConstraint(
+            model_name='sitegroup',
+            constraint=models.UniqueConstraint(fields=('parent', 'name'), name='dcim_sitegroup_parent_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='sitegroup',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_sitegroup_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='sitegroup',
+            constraint=models.UniqueConstraint(fields=('parent', 'slug'), name='dcim_sitegroup_parent_slug'),
+        ),
+        migrations.AddConstraint(
+            model_name='sitegroup',
+            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_sitegroup_slug'),
+        ),
+        migrations.AddField(
+            model_name='devicerole',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='location',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='manufacturer',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='platform',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='rackrole',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='region',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AddField(
+            model_name='sitegroup',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.RenameField(
+            model_name='consoleport',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='consoleport',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='consoleserverport',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='consoleserverport',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='frontport',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='frontport',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='interface',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='interface',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='powerfeed',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='powerfeed',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='poweroutlet',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='poweroutlet',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='powerport',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='powerport',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.RenameField(
+            model_name='rearport',
+            old_name='_cable_peer_id',
+            new_name='_link_peer_id',
+        ),
+        migrations.RenameField(
+            model_name='rearport',
+            old_name='_cable_peer_type',
+            new_name='_link_peer_type',
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='rf_role',
+            field=models.CharField(blank=True, max_length=30),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='rf_channel',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='rf_channel_frequency',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='rf_channel_width',
+            field=models.DecimalField(blank=True, decimal_places=3, max_digits=7, null=True),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='tx_power',
+            field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(127)]),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='wireless_lans',
+            field=models.ManyToManyField(blank=True, related_name='interfaces', to='wireless.wirelesslan'),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='wireless_link',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wireless.wirelesslink'),
+        ),
+        migrations.AddField(
+            model_name='site',
+            name='asns',
+            field=models.ManyToManyField(blank=True, related_name='sites', to='ipam.asn'),
+        ),
+        migrations.AlterField(
+            model_name='device',
+            name='primary_ip4',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'),
+        ),
+        migrations.AlterField(
+            model_name='device',
+            name='primary_ip6',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'),
+        ),
+        migrations.RemoveField(
+            model_name='site',
+            name='asn',
+        ),
+        migrations.RemoveField(
+            model_name='site',
+            name='contact_email',
+        ),
+        migrations.RemoveField(
+            model_name='site',
+            name='contact_name',
+        ),
+        migrations.RemoveField(
+            model_name='site',
+            name='contact_phone',
+        ),
+        migrations.RunSQL(
+            sql="\n            DO $$\n            DECLARE\n                idx record;\n            BEGIN\n                FOR idx IN\n                    SELECT indexname AS old_name,\n                           replace(indexname, 'module', 'inventoryitem') AS new_name\n                    FROM pg_indexes\n                    WHERE schemaname = 'public' AND\n                          tablename = 'dcim_inventoryitem' AND\n                          indexname LIKE 'dcim_module_%'\n                LOOP\n                    EXECUTE format(\n                        'ALTER INDEX %I RENAME TO %I;',\n                        idx.old_name,\n                        idx.new_name\n                    );\n                END LOOP;\n            END$$;\n            ",
+        ),
+        migrations.AlterModelOptions(
+            name='consoleporttemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='consoleserverporttemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='frontporttemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='interfacetemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='poweroutlettemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='powerporttemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterModelOptions(
+            name='rearporttemplate',
+            options={'ordering': ('device_type', 'module_type', '_name')},
+        ),
+        migrations.AlterField(
+            model_name='consoleporttemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverporttemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='frontporttemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='interfacetemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlettemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='powerporttemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.AlterField(
+            model_name='rearporttemplate',
+            name='device_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
+        ),
+        migrations.CreateModel(
+            name='ModuleType',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('model', models.CharField(max_length=100)),
+                ('part_number', models.CharField(blank=True, max_length=50)),
+                ('comments', models.TextField(blank=True)),
+                ('manufacturer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='module_types', to='dcim.manufacturer')),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+            ],
+            options={
+                'ordering': ('manufacturer', 'model'),
+                'unique_together': {('manufacturer', 'model')},
+            },
+        ),
+        migrations.CreateModel(
+            name='ModuleBay',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=64)),
+                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
+                ('label', models.CharField(blank=True, max_length=64)),
+                ('position', models.CharField(blank=True, max_length=30)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device')),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+            ],
+            options={
+                'ordering': ('device', '_name'),
+                'unique_together': {('device', 'name')},
+            },
+        ),
+        migrations.CreateModel(
+            name='Module',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('local_context_data', models.JSONField(blank=True, null=True)),
+                ('serial', models.CharField(blank=True, max_length=50)),
+                ('asset_tag', models.CharField(blank=True, max_length=50, null=True, unique=True)),
+                ('comments', models.TextField(blank=True)),
+                ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='dcim.device')),
+                ('module_bay', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='installed_module', to='dcim.modulebay')),
+                ('module_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.moduletype')),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+            ],
+            options={
+                'ordering': ('module_bay',),
+            },
+        ),
+        migrations.AddField(
+            model_name='consoleport',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='consoleporttemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='consoleserverport',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='consoleserverporttemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='frontport',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='frontporttemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='poweroutlet',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='poweroutlettemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='powerport',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='powerporttemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AddField(
+            model_name='rearport',
+            name='module',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
+        ),
+        migrations.AddField(
+            model_name='rearporttemplate',
+            name='module_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
+        ),
+        migrations.AlterUniqueTogether(
+            name='consoleporttemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='consoleserverporttemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='frontporttemplate',
+            unique_together={('rear_port', 'rear_port_position'), ('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='interfacetemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='poweroutlettemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='powerporttemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='rearporttemplate',
+            unique_together={('device_type', 'name'), ('module_type', 'name')},
+        ),
+        migrations.CreateModel(
+            name='InventoryItemRole',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=100, unique=True)),
+                ('slug', models.SlugField(max_length=100, unique=True)),
+                ('color', utilities.fields.ColorField(default='9e9e9e', max_length=6)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+            ],
+            options={
+                'ordering': ('name',),
+            },
+        ),
+        migrations.AddField(
+            model_name='inventoryitem',
+            name='role',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.inventoryitemrole'),
+        ),
+        migrations.AddField(
+            model_name='inventoryitem',
+            name='component_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='inventoryitem',
+            name='component_type',
+            field=models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'poweroutlet', 'powerport', 'rearport'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='vrf',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interfaces', to='ipam.vrf'),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='duplex',
+            field=models.CharField(blank=True, max_length=50, null=True),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='speed',
+            field=models.PositiveIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='cable',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='cablepath',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='consoleport',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='consoleporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverport',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='device',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='devicebay',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='devicebaytemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='devicerole',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='devicetype',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='frontport',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='frontporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='interface',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='interfacetemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='inventoryitem',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='location',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='manufacturer',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='platform',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='powerfeed',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlet',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlettemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='powerpanel',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='powerport',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='powerporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='rack',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='rackreservation',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='rackrole',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='rearport',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='rearporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='region',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='site',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='sitegroup',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='virtualchassis',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='cable',
+            name='termination_a_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='cable',
+            name='termination_b_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='cablepath',
+            name='destination_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='cablepath',
+            name='origin_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='consoleport',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverport',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='frontport',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='interface',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerfeed',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlet',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerport',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rearport',
+            name='_link_peer_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='cable',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleport',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverport',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='consoleserverporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='device',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='devicebay',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='devicebaytemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='devicerole',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='devicetype',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='frontport',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='frontporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='interface',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='interfacetemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='inventoryitem',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.CreateModel(
+            name='InventoryItemTemplate',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=64)),
+                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
+                ('label', models.CharField(blank=True, max_length=64)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('component_id', models.PositiveBigIntegerField(blank=True, null=True)),
+                ('part_id', models.CharField(blank=True, max_length=50)),
+                ('lft', models.PositiveIntegerField(editable=False)),
+                ('rght', models.PositiveIntegerField(editable=False)),
+                ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
+                ('level', models.PositiveIntegerField(editable=False)),
+                ('component_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleporttemplate', 'consoleserverporttemplate', 'frontporttemplate', 'interfacetemplate', 'poweroutlettemplate', 'powerporttemplate', 'rearporttemplate'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')),
+                ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')),
+                ('manufacturer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.manufacturer')),
+                ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.inventoryitemtemplate')),
+                ('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.inventoryitemrole')),
+            ],
+            options={
+                'ordering': ('device_type__id', 'parent__id', '_name'),
+                'unique_together': {('device_type', 'parent', 'name')},
+            },
+        ),
+        migrations.AlterField(
+            model_name='location',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='manufacturer',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.CreateModel(
+            name='ModuleBayTemplate',
+            fields=[
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('name', models.CharField(max_length=64)),
+                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
+                ('label', models.CharField(blank=True, max_length=64)),
+                ('position', models.CharField(blank=True, max_length=30)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')),
+            ],
+            options={
+                'ordering': ('device_type', '_name'),
+                'unique_together': {('device_type', 'name')},
+            },
+        ),
+        migrations.AlterField(
+            model_name='platform',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerfeed',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlet',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='poweroutlettemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerpanel',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerport',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rack',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rackreservation',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rackrole',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rearport',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='rearporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='region',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='site',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='sitegroup',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='virtualchassis',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='devicetype',
+            name='u_height',
+            field=models.DecimalField(decimal_places=1, default=1.0, max_digits=4),
+        ),
+        migrations.AlterField(
+            model_name='device',
+            name='position',
+            field=models.DecimalField(blank=True, decimal_places=1, max_digits=4, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100.5)]),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='poe_mode',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='poe_type',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='poe_mode',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='poe_type',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='location',
+            name='status',
+            field=models.CharField(default='active', max_length=50),
+        ),
+        migrations.CreateModel(
+            name='CableTermination',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('cable_end', models.CharField(max_length=1)),
+                ('termination_id', models.PositiveBigIntegerField()),
+                ('cable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='dcim.cable')),
+                ('termination_type', models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')),
+                ('_device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
+                ('_rack', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.rack')),
+                ('_location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.location')),
+                ('_site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.site')),
+            ],
+            options={
+                'ordering': ('cable', 'cable_end', 'pk'),
+            },
+        ),
+        migrations.AddConstraint(
+            model_name='cabletermination',
+            constraint=models.UniqueConstraint(fields=('termination_type', 'termination_id'), name='dcim_cable_termination_unique_termination'),
+        ),
+        migrations.RenameField(
+            model_name='cablepath',
+            old_name='path',
+            new_name='_nodes',
+        ),
+        migrations.AddField(
+            model_name='cablepath',
+            name='path',
+            field=models.JSONField(default=list),
+        ),
+        migrations.AddField(
+            model_name='cablepath',
+            name='is_complete',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddField(
+            model_name='consoleport',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='consoleserverport',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='frontport',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='powerfeed',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='poweroutlet',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='powerport',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+        migrations.AddField(
+            model_name='rearport',
+            name='cable_end',
+            field=models.CharField(blank=True, max_length=1),
+        ),
+    ]

+ 0 - 16
netbox/dcim/migrations/0132_cable_length.py

@@ -1,16 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0131_consoleport_speed'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='cable',
-            name='length',
-            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
-        ),
-    ]

+ 0 - 32
netbox/dcim/migrations/0133_port_colors.py

@@ -1,32 +0,0 @@
-from django.db import migrations
-import utilities.fields
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0132_cable_length'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='frontport',
-            name='color',
-            field=utilities.fields.ColorField(blank=True, max_length=6),
-        ),
-        migrations.AddField(
-            model_name='frontporttemplate',
-            name='color',
-            field=utilities.fields.ColorField(blank=True, max_length=6),
-        ),
-        migrations.AddField(
-            model_name='rearport',
-            name='color',
-            field=utilities.fields.ColorField(blank=True, max_length=6),
-        ),
-        migrations.AddField(
-            model_name='rearporttemplate',
-            name='color',
-            field=utilities.fields.ColorField(blank=True, max_length=6),
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0134_interface_wwn_bridge.py

@@ -1,23 +0,0 @@
-import dcim.fields
-import django.db.models.deletion
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0133_port_colors'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interface',
-            name='wwn',
-            field=dcim.fields.WWNField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='bridge',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interface'),
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0135_tenancy_extensions.py

@@ -1,23 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('tenancy', '0002_tenant_ordering'),
-        ('dcim', '0134_interface_wwn_bridge'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='location',
-            name='tenant',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='locations', to='tenancy.tenant'),
-        ),
-        migrations.AddField(
-            model_name='cable',
-            name='tenant',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='cables', to='tenancy.tenant'),
-        ),
-    ]

+ 0 - 21
netbox/dcim/migrations/0136_device_airflow.py

@@ -1,21 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0135_tenancy_extensions'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='devicetype',
-            name='airflow',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='airflow',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-    ]

+ 0 - 83
netbox/dcim/migrations/0137_relax_uniqueness_constraints.py

@@ -1,83 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0136_device_airflow'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='region',
-            name='name',
-            field=models.CharField(max_length=100),
-        ),
-        migrations.AlterField(
-            model_name='region',
-            name='slug',
-            field=models.SlugField(max_length=100),
-        ),
-        migrations.AlterField(
-            model_name='sitegroup',
-            name='name',
-            field=models.CharField(max_length=100),
-        ),
-        migrations.AlterField(
-            model_name='sitegroup',
-            name='slug',
-            field=models.SlugField(max_length=100),
-        ),
-        migrations.AlterUniqueTogether(
-            name='location',
-            unique_together=set(),
-        ),
-        migrations.AddConstraint(
-            model_name='location',
-            constraint=models.UniqueConstraint(fields=('site', 'parent', 'name'), name='dcim_location_parent_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='location',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'name'), name='dcim_location_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='location',
-            constraint=models.UniqueConstraint(fields=('site', 'parent', 'slug'), name='dcim_location_parent_slug'),
-        ),
-        migrations.AddConstraint(
-            model_name='location',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('site', 'slug'), name='dcim_location_slug'),
-        ),
-        migrations.AddConstraint(
-            model_name='region',
-            constraint=models.UniqueConstraint(fields=('parent', 'name'), name='dcim_region_parent_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='region',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_region_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='region',
-            constraint=models.UniqueConstraint(fields=('parent', 'slug'), name='dcim_region_parent_slug'),
-        ),
-        migrations.AddConstraint(
-            model_name='region',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_region_slug'),
-        ),
-        migrations.AddConstraint(
-            model_name='sitegroup',
-            constraint=models.UniqueConstraint(fields=('parent', 'name'), name='dcim_sitegroup_parent_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='sitegroup',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('name',), name='dcim_sitegroup_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='sitegroup',
-            constraint=models.UniqueConstraint(fields=('parent', 'slug'), name='dcim_sitegroup_parent_slug'),
-        ),
-        migrations.AddConstraint(
-            model_name='sitegroup',
-            constraint=models.UniqueConstraint(condition=models.Q(('parent', None)), fields=('slug',), name='dcim_sitegroup_slug'),
-        ),
-    ]

+ 0 - 50
netbox/dcim/migrations/0138_extend_tag_support.py

@@ -1,50 +0,0 @@
-# Generated by Django 3.2.8 on 2021-10-21 14:50
-
-from django.db import migrations
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0062_clear_secrets_changelog'),
-        ('dcim', '0137_relax_uniqueness_constraints'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='devicerole',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='location',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='manufacturer',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='platform',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='rackrole',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='region',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-        migrations.AddField(
-            model_name='sitegroup',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-    ]

+ 0 - 91
netbox/dcim/migrations/0139_rename_cable_peer.py

@@ -1,91 +0,0 @@
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0138_extend_tag_support'),
-    ]
-
-    operations = [
-        migrations.RenameField(
-            model_name='consoleport',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='consoleport',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='consoleserverport',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='consoleserverport',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='frontport',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='frontport',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='interface',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='interface',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='powerfeed',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='powerfeed',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='poweroutlet',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='poweroutlet',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='powerport',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='powerport',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-        migrations.RenameField(
-            model_name='rearport',
-            old_name='_cable_peer_id',
-            new_name='_link_peer_id',
-        ),
-        migrations.RenameField(
-            model_name='rearport',
-            old_name='_cable_peer_type',
-            new_name='_link_peer_type',
-        ),
-    ]

+ 0 - 49
netbox/dcim/migrations/0140_wireless.py

@@ -1,49 +0,0 @@
-from django.db import migrations, models
-import django.core.validators
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0139_rename_cable_peer'),
-        ('wireless', '0001_wireless'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interface',
-            name='rf_role',
-            field=models.CharField(blank=True, max_length=30),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='rf_channel',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='rf_channel_frequency',
-            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='rf_channel_width',
-            field=models.DecimalField(blank=True, decimal_places=3, max_digits=7, null=True),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='tx_power',
-            field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(127)]),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='wireless_lans',
-            field=models.ManyToManyField(blank=True, related_name='interfaces', to='wireless.WirelessLAN'),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='wireless_link',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wireless.wirelesslink'),
-        ),
-    ]

+ 0 - 19
netbox/dcim/migrations/0141_asn_model.py

@@ -1,19 +0,0 @@
-# Generated by Django 3.2.8 on 2021-11-02 16:16
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('ipam', '0053_asn_model'),
-        ('dcim', '0140_wireless'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='site',
-            name='asns',
-            field=models.ManyToManyField(blank=True, related_name='sites', to='ipam.ASN'),
-        ),
-    ]

+ 0 - 29
netbox/dcim/migrations/0142_rename_128gfc_qsfp28.py

@@ -1,29 +0,0 @@
-from django.db import migrations
-
-OLD_VALUE = '128gfc-sfp28'
-NEW_VALUE = '128gfc-qsfp28'
-
-
-def correct_type(apps, schema_editor):
-    """
-    Correct TYPE_128GFC_QSFP28 interface type.
-    """
-    Interface = apps.get_model('dcim', 'Interface')
-    InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
-
-    for model in (Interface, InterfaceTemplate):
-        model.objects.filter(type=OLD_VALUE).update(type=NEW_VALUE)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0141_asn_model'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=correct_type,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0143_remove_primary_for_related_name.py

@@ -1,23 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('ipam', '0053_asn_model'),
-        ('dcim', '0142_rename_128gfc_qsfp28'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='device',
-            name='primary_ip4',
-            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'),
-        ),
-        migrations.AlterField(
-            model_name='device',
-            name='primary_ip6',
-            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'),
-        ),
-    ]

+ 0 - 31
netbox/dcim/migrations/0144_fix_cable_abs_length.py

@@ -1,31 +0,0 @@
-from django.db import migrations
-
-from utilities.utils import to_meters
-
-
-def recalculate_abs_length(apps, schema_editor):
-    """
-    Recalculate absolute lengths for all cables with a length and length unit defined. Fixes
-    incorrectly calculated values as reported under bug #8377.
-    """
-    Cable = apps.get_model('dcim', 'Cable')
-
-    cables = Cable.objects.filter(length__isnull=False).exclude(length_unit='')
-    for cable in cables:
-        cable._abs_length = to_meters(cable.length, cable.length_unit)
-
-    Cable.objects.bulk_update(cables, ['_abs_length'], batch_size=100)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0143_remove_primary_for_related_name'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=recalculate_abs_length,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 59
netbox/dcim/migrations/0145_site_remove_deprecated_fields.py

@@ -1,59 +0,0 @@
-import os
-
-from django.db import migrations
-from django.db.utils import DataError
-
-
-def check_legacy_data(apps, schema_editor):
-    """
-    Abort the migration if any legacy site fields still contain data.
-    """
-    Site = apps.get_model('dcim', 'Site')
-
-    site_count = Site.objects.exclude(asn__isnull=True).count()
-    if site_count and 'NETBOX_DELETE_LEGACY_DATA' not in os.environ:
-        raise DataError(
-            f"Unable to proceed with deleting asn field from Site model: Found {site_count} sites with "
-            f"legacy ASN data. Please ensure all legacy site ASN data has been migrated to ASN objects "
-            f"before proceeding. Or, set the NETBOX_DELETE_LEGACY_DATA environment variable to bypass "
-            f"this safeguard and delete all legacy site ASN data."
-        )
-
-    site_count = Site.objects.exclude(contact_name='', contact_phone='', contact_email='').count()
-    if site_count and 'NETBOX_DELETE_LEGACY_DATA' not in os.environ:
-        raise DataError(
-            f"Unable to proceed with deleting contact fields from Site model: Found {site_count} sites "
-            f"with legacy contact data. Please ensure all legacy site contact data has been migrated to "
-            f"contact objects before proceeding. Or, set the NETBOX_DELETE_LEGACY_DATA environment "
-            f"variable to bypass this safeguard and delete all legacy site contact data."
-        )
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0144_fix_cable_abs_length'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=check_legacy_data,
-            reverse_code=migrations.RunPython.noop
-        ),
-        migrations.RemoveField(
-            model_name='site',
-            name='asn',
-        ),
-        migrations.RemoveField(
-            model_name='site',
-            name='contact_email',
-        ),
-        migrations.RemoveField(
-            model_name='site',
-            name='contact_name',
-        ),
-        migrations.RemoveField(
-            model_name='site',
-            name='contact_phone',
-        ),
-    ]

+ 0 - 279
netbox/dcim/migrations/0146_modules.py

@@ -1,279 +0,0 @@
-from utilities.json import CustomFieldJSONEncoder
-from django.db import migrations, models
-import django.db.models.deletion
-import taggit.managers
-import utilities.fields
-import utilities.ordering
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0066_customfield_name_validation'),
-        ('dcim', '0145_site_remove_deprecated_fields'),
-    ]
-
-    operations = [
-        # Rename any indexes left over from the old Module model (now InventoryItem) (#8656)
-        migrations.RunSQL(
-            """
-            DO $$
-            DECLARE
-                idx record;
-            BEGIN
-                FOR idx IN
-                    SELECT indexname AS old_name,
-                           replace(indexname, 'module', 'inventoryitem') AS new_name
-                    FROM pg_indexes
-                    WHERE schemaname = 'public' AND
-                          tablename = 'dcim_inventoryitem' AND
-                          indexname LIKE 'dcim_module_%'
-                LOOP
-                    EXECUTE format(
-                        'ALTER INDEX %I RENAME TO %I;',
-                        idx.old_name,
-                        idx.new_name
-                    );
-                END LOOP;
-            END$$;
-            """
-        ),
-
-        migrations.AlterModelOptions(
-            name='consoleporttemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='consoleserverporttemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='frontporttemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='interfacetemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='poweroutlettemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='powerporttemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterModelOptions(
-            name='rearporttemplate',
-            options={'ordering': ('device_type', 'module_type', '_name')},
-        ),
-        migrations.AlterField(
-            model_name='consoleporttemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverporttemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='frontporttemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='interfacetemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlettemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='powerporttemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.AlterField(
-            model_name='rearporttemplate',
-            name='device_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype'),
-        ),
-        migrations.CreateModel(
-            name='ModuleType',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('model', models.CharField(max_length=100)),
-                ('part_number', models.CharField(blank=True, max_length=50)),
-                ('comments', models.TextField(blank=True)),
-                ('manufacturer', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='module_types', to='dcim.manufacturer')),
-                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
-            ],
-            options={
-                'ordering': ('manufacturer', 'model'),
-                'unique_together': {('manufacturer', 'model')},
-            },
-        ),
-        migrations.CreateModel(
-            name='ModuleBay',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('name', models.CharField(max_length=64)),
-                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
-                ('label', models.CharField(blank=True, max_length=64)),
-                ('position', models.CharField(blank=True, max_length=30)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.device')),
-                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
-            ],
-            options={
-                'ordering': ('device', '_name'),
-                'unique_together': {('device', 'name')},
-            },
-        ),
-        migrations.CreateModel(
-            name='Module',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('local_context_data', models.JSONField(blank=True, null=True)),
-                ('serial', models.CharField(blank=True, max_length=50)),
-                ('asset_tag', models.CharField(blank=True, max_length=50, null=True, unique=True)),
-                ('comments', models.TextField(blank=True)),
-                ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modules', to='dcim.device')),
-                ('module_bay', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='installed_module', to='dcim.modulebay')),
-                ('module_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='instances', to='dcim.moduletype')),
-                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
-            ],
-            options={
-                'ordering': ('module_bay',),
-            },
-        ),
-        migrations.AddField(
-            model_name='consoleport',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='consoleporttemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='consoleserverport',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='consoleserverporttemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='frontport',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='frontporttemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='poweroutlet',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='poweroutlettemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='powerport',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='powerporttemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AddField(
-            model_name='rearport',
-            name='module',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.module'),
-        ),
-        migrations.AddField(
-            model_name='rearporttemplate',
-            name='module_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.moduletype'),
-        ),
-        migrations.AlterUniqueTogether(
-            name='consoleporttemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='consoleserverporttemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='frontporttemplate',
-            unique_together={('device_type', 'name'), ('rear_port', 'rear_port_position'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='interfacetemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='poweroutlettemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='powerporttemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.AlterUniqueTogether(
-            name='rearporttemplate',
-            unique_together={('device_type', 'name'), ('module_type', 'name')},
-        ),
-        migrations.CreateModel(
-            name='ModuleBayTemplate',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('name', models.CharField(max_length=64)),
-                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
-                ('label', models.CharField(blank=True, max_length=64)),
-                ('position', models.CharField(blank=True, max_length=30)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')),
-            ],
-            options={
-                'ordering': ('device_type', '_name'),
-                'unique_together': {('device_type', 'name')},
-            },
-        ),
-    ]

+ 0 - 38
netbox/dcim/migrations/0147_inventoryitemrole.py

@@ -1,38 +0,0 @@
-from utilities.json import CustomFieldJSONEncoder
-from django.db import migrations, models
-import django.db.models.deletion
-import taggit.managers
-import utilities.fields
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0068_configcontext_cluster_types'),
-        ('dcim', '0146_modules'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='InventoryItemRole',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('name', models.CharField(max_length=100, unique=True)),
-                ('slug', models.SlugField(max_length=100, unique=True)),
-                ('color', utilities.fields.ColorField(default='9e9e9e', max_length=6)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
-            ],
-            options={
-                'ordering': ('name',),
-            },
-        ),
-        migrations.AddField(
-            model_name='inventoryitem',
-            name='role',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.inventoryitemrole'),
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0148_inventoryitem_component.py

@@ -1,23 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('dcim', '0147_inventoryitemrole'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='inventoryitem',
-            name='component_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='inventoryitem',
-            name='component_type',
-            field=models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'poweroutlet', 'powerport', 'rearport'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype'),
-        ),
-    ]

+ 0 - 43
netbox/dcim/migrations/0149_inventoryitem_templates.py

@@ -1,43 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-import mptt.fields
-import utilities.fields
-import utilities.ordering
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('dcim', '0148_inventoryitem_component'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='InventoryItemTemplate',
-            fields=[
-                ('created', models.DateField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('id', models.BigAutoField(primary_key=True, serialize=False)),
-                ('name', models.CharField(max_length=64)),
-                ('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
-                ('label', models.CharField(blank=True, max_length=64)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('component_id', models.PositiveBigIntegerField(blank=True, null=True)),
-                ('part_id', models.CharField(blank=True, max_length=50)),
-                ('lft', models.PositiveIntegerField(editable=False)),
-                ('rght', models.PositiveIntegerField(editable=False)),
-                ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
-                ('level', models.PositiveIntegerField(editable=False)),
-                ('component_type', models.ForeignKey(blank=True, limit_choices_to=models.Q(('app_label', 'dcim'), ('model__in', ('consoleporttemplate', 'consoleserverporttemplate', 'frontporttemplate', 'interfacetemplate', 'poweroutlettemplate', 'powerporttemplate', 'rearporttemplate'))), null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')),
-                ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='%(class)ss', to='dcim.devicetype')),
-                ('manufacturer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.manufacturer')),
-                ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.inventoryitemtemplate')),
-                ('role', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_item_templates', to='dcim.inventoryitemrole')),
-            ],
-            options={
-                'ordering': ('device_type__id', 'parent__id', '_name'),
-                'unique_together': {('device_type', 'parent', 'name')},
-            },
-        ),
-    ]

+ 0 - 20
netbox/dcim/migrations/0150_interface_vrf.py

@@ -1,20 +0,0 @@
-# Generated by Django 3.2.11 on 2022-01-07 18:34
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('ipam', '0054_vlangroup_min_max_vids'),
-        ('dcim', '0149_inventoryitem_templates'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interface',
-            name='vrf',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interfaces', to='ipam.vrf'),
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0151_interface_speed_duplex.py

@@ -1,23 +0,0 @@
-# Generated by Django 3.2.10 on 2022-01-08 18:23
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0150_interface_vrf'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interface',
-            name='duplex',
-            field=models.CharField(blank=True, max_length=50, null=True),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='speed',
-            field=models.PositiveIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 274
netbox/dcim/migrations/0152_standardize_id_fields.py

@@ -1,274 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0151_interface_speed_duplex'),
-    ]
-
-    operations = [
-        # Model IDs
-        migrations.AlterField(
-            model_name='cable',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='cablepath',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='consoleport',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='consoleporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverport',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='device',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='devicebay',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='devicebaytemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='devicerole',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='devicetype',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='frontport',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='frontporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='interface',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='interfacetemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitem',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitemrole',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitemtemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='location',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='manufacturer',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='module',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='modulebay',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='modulebaytemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='moduletype',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='platform',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='powerfeed',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlet',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlettemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='powerpanel',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='powerport',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='powerporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='rack',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='rackreservation',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='rackrole',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='rearport',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='rearporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='region',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='site',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='sitegroup',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='virtualchassis',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-
-        # GFK IDs
-        migrations.AlterField(
-            model_name='cable',
-            name='termination_a_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='cable',
-            name='termination_b_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='cablepath',
-            name='destination_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='cablepath',
-            name='origin_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='consoleport',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverport',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='frontport',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='interface',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerfeed',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlet',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerport',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rearport',
-            name='_link_peer_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 208
netbox/dcim/migrations/0153_created_datetimefield.py

@@ -1,208 +0,0 @@
-# Generated by Django 4.0.2 on 2022-02-08 18:54
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0152_standardize_id_fields'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='cable',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleport',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverport',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='consoleserverporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='device',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='devicebay',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='devicebaytemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='devicerole',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='devicetype',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='frontport',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='frontporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='interface',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='interfacetemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitem',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitemrole',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='inventoryitemtemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='location',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='manufacturer',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='module',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='modulebay',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='modulebaytemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='moduletype',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='platform',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerfeed',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlet',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='poweroutlettemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerpanel',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerport',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='powerporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rack',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rackreservation',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rackrole',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rearport',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='rearporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='region',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='site',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='sitegroup',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='virtualchassis',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-    ]

+ 0 - 23
netbox/dcim/migrations/0154_half_height_rack_units.py

@@ -1,23 +0,0 @@
-import django.contrib.postgres.fields
-import django.core.validators
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0153_created_datetimefield'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='devicetype',
-            name='u_height',
-            field=models.DecimalField(decimal_places=1, default=1.0, max_digits=4),
-        ),
-        migrations.AlterField(
-            model_name='device',
-            name='position',
-            field=models.DecimalField(blank=True, decimal_places=1, max_digits=4, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100.5)]),
-        ),
-    ]

+ 0 - 33
netbox/dcim/migrations/0155_interface_poe_mode_type.py

@@ -1,33 +0,0 @@
-# Generated by Django 4.0.5 on 2022-06-22 00:36
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0154_half_height_rack_units'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interface',
-            name='poe_mode',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='poe_type',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='poe_mode',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='poe_type',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-    ]

+ 0 - 18
netbox/dcim/migrations/0156_location_status.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.0.5 on 2022-06-22 17:10
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0155_interface_poe_mode_type'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='location',
-            name='status',
-            field=models.CharField(default='active', max_length=50),
-        ),
-    ]

+ 0 - 95
netbox/dcim/migrations/0157_new_cabling_models.py

@@ -1,95 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('dcim', '0156_location_status'),
-    ]
-
-    operations = [
-
-        # Create CableTermination model
-        migrations.CreateModel(
-            name='CableTermination',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('cable_end', models.CharField(max_length=1)),
-                ('termination_id', models.PositiveBigIntegerField()),
-                ('cable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='dcim.cable')),
-                ('termination_type', models.ForeignKey(limit_choices_to=models.Q(models.Q(models.Q(('app_label', 'circuits'), ('model__in', ('circuittermination',))), models.Q(('app_label', 'dcim'), ('model__in', ('consoleport', 'consoleserverport', 'frontport', 'interface', 'powerfeed', 'poweroutlet', 'powerport', 'rearport'))), _connector='OR')), on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.contenttype')),
-                ('_device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
-                ('_rack', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.rack')),
-                ('_location', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.location')),
-                ('_site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dcim.site')),
-            ],
-            options={
-                'ordering': ('cable', 'cable_end', 'pk'),
-            },
-        ),
-        migrations.AddConstraint(
-            model_name='cabletermination',
-            constraint=models.UniqueConstraint(fields=('termination_type', 'termination_id'), name='dcim_cable_termination_unique_termination'),
-        ),
-
-        # Update CablePath model
-        migrations.RenameField(
-            model_name='cablepath',
-            old_name='path',
-            new_name='_nodes',
-        ),
-        migrations.AddField(
-            model_name='cablepath',
-            name='path',
-            field=models.JSONField(default=list),
-        ),
-        migrations.AddField(
-            model_name='cablepath',
-            name='is_complete',
-            field=models.BooleanField(default=False),
-        ),
-
-        # Add cable_end field to cable termination models
-        migrations.AddField(
-            model_name='consoleport',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='consoleserverport',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='frontport',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='powerfeed',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='poweroutlet',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='powerport',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-        migrations.AddField(
-            model_name='rearport',
-            name='cable_end',
-            field=models.CharField(blank=True, max_length=1),
-        ),
-    ]

+ 0 - 87
netbox/dcim/migrations/0158_populate_cable_terminations.py

@@ -1,87 +0,0 @@
-import sys
-
-from django.db import migrations
-
-
-def cache_related_objects(termination):
-    """
-    Replicate caching logic from CableTermination.cache_related_objects()
-    """
-    attrs = {}
-
-    # Device components
-    if getattr(termination, 'device', None):
-        attrs['_device'] = termination.device
-        attrs['_rack'] = termination.device.rack
-        attrs['_location'] = termination.device.location
-        attrs['_site'] = termination.device.site
-
-    # Power feeds
-    elif getattr(termination, 'rack', None):
-        attrs['_rack'] = termination.rack
-        attrs['_location'] = termination.rack.location
-        attrs['_site'] = termination.rack.site
-
-    # Circuit terminations
-    elif getattr(termination, 'site', None):
-        attrs['_site'] = termination.site
-
-    return attrs
-
-
-def populate_cable_terminations(apps, schema_editor):
-    """
-    Replicate terminations from the Cable model into CableTermination instances.
-    """
-    ContentType = apps.get_model('contenttypes', 'ContentType')
-    Cable = apps.get_model('dcim', 'Cable')
-    CableTermination = apps.get_model('dcim', 'CableTermination')
-
-    # Retrieve the necessary data from Cable objects
-    cables = Cable.objects.values(
-        'id', 'termination_a_type', 'termination_a_id', 'termination_b_type', 'termination_b_id'
-    )
-
-    # Queue CableTerminations to be created
-    cable_terminations = []
-    cable_count = cables.count()
-    for i, cable in enumerate(cables, start=1):
-        for cable_end in ('a', 'b'):
-            # We must manually instantiate the termination object, because GFK fields are not
-            # supported within migrations.
-            termination_ct = ContentType.objects.get(pk=cable[f'termination_{cable_end}_type'])
-            termination_model = apps.get_model(termination_ct.app_label, termination_ct.model)
-            termination = termination_model.objects.get(pk=cable[f'termination_{cable_end}_id'])
-
-            cable_terminations.append(CableTermination(
-                cable_id=cable['id'],
-                cable_end=cable_end.upper(),
-                termination_type_id=cable[f'termination_{cable_end}_type'],
-                termination_id=cable[f'termination_{cable_end}_id'],
-                **cache_related_objects(termination)
-            ))
-
-        # Output progress occasionally
-        if 'test' not in sys.argv and not i % 100:
-            progress = float(i) * 100 / cable_count
-            if i == 100:
-                print('')
-            sys.stdout.write(f"\r    Updated {i}/{cable_count} cables ({progress:.2f}%)")
-            sys.stdout.flush()
-
-    # Bulk create the termination objects
-    CableTermination.objects.bulk_create(cable_terminations, batch_size=100)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0157_new_cabling_models'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=populate_cable_terminations,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 50
netbox/dcim/migrations/0159_populate_cable_paths.py

@@ -1,50 +0,0 @@
-from django.db import migrations
-
-from dcim.utils import compile_path_node
-
-
-def populate_cable_paths(apps, schema_editor):
-    """
-    Replicate terminations from the Cable model into CableTermination instances.
-    """
-    CablePath = apps.get_model('dcim', 'CablePath')
-
-    # Construct the new two-dimensional path, and add the origin & destination objects to the nodes list
-    cable_paths = []
-    for cablepath in CablePath.objects.all():
-
-        # Origin
-        origin = compile_path_node(cablepath.origin_type_id, cablepath.origin_id)
-        cablepath.path.append([origin])
-        cablepath._nodes.insert(0, origin)
-
-        # Transit nodes
-        cablepath.path.extend([
-            [node] for node in cablepath._nodes[1:]
-        ])
-
-        # Destination
-        if cablepath.destination_id:
-            destination = compile_path_node(cablepath.destination_type_id, cablepath.destination_id)
-            cablepath.path.append([destination])
-            cablepath._nodes.append(destination)
-            cablepath.is_complete = True
-
-        cable_paths.append(cablepath)
-
-    # Bulk update all CableTerminations
-    CablePath.objects.bulk_update(cable_paths, fields=('path', '_nodes', 'is_complete'), batch_size=100)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0158_populate_cable_terminations'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=populate_cable_paths,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 46
netbox/dcim/migrations/0160_populate_cable_ends.py

@@ -1,46 +0,0 @@
-from django.db import migrations
-
-
-def populate_cable_terminations(apps, schema_editor):
-    Cable = apps.get_model('dcim', 'Cable')
-
-    cable_termination_models = (
-        apps.get_model('dcim', 'ConsolePort'),
-        apps.get_model('dcim', 'ConsoleServerPort'),
-        apps.get_model('dcim', 'PowerPort'),
-        apps.get_model('dcim', 'PowerOutlet'),
-        apps.get_model('dcim', 'Interface'),
-        apps.get_model('dcim', 'FrontPort'),
-        apps.get_model('dcim', 'RearPort'),
-        apps.get_model('dcim', 'PowerFeed'),
-        apps.get_model('circuits', 'CircuitTermination'),
-    )
-
-    for model in cable_termination_models:
-        model.objects.filter(
-            id__in=Cable.objects.filter(
-                termination_a_type__app_label=model._meta.app_label,
-                termination_a_type__model=model._meta.model_name
-            ).values_list('termination_a_id', flat=True)
-        ).update(cable_end='A')
-        model.objects.filter(
-            id__in=Cable.objects.filter(
-                termination_b_type__app_label=model._meta.app_label,
-                termination_b_type__model=model._meta.model_name
-            ).values_list('termination_b_id', flat=True)
-        ).update(cable_end='B')
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0037_new_cabling_models'),
-        ('dcim', '0159_populate_cable_paths'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=populate_cable_terminations,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 294 - 2
netbox/dcim/migrations/0162_unique_constraints.py → netbox/dcim/migrations/0160_squashed_0166.py

@@ -1,14 +1,146 @@
-from django.db import migrations, models
 import django.db.models.functions.text
+import taggit.managers
+from django.db import migrations, models
+
+import utilities.json
 
 
 class Migration(migrations.Migration):
 
-    dependencies = [
+    replaces = [
+        ('dcim', '0160_populate_cable_ends'),
         ('dcim', '0161_cabling_cleanup'),
+        ('dcim', '0162_unique_constraints'),
+        ('dcim', '0163_weight_fields'),
+        ('dcim', '0164_rack_mounting_depth'),
+        ('dcim', '0165_standardize_description_comments'),
+        ('dcim', '0166_virtualdevicecontext')
+    ]
+
+    dependencies = [
+        ('ipam', '0047_squashed_0053'),
+        ('tenancy', '0009_standardize_description_comments'),
+        ('circuits', '0037_new_cabling_models'),
+        ('dcim', '0159_populate_cable_paths'),
     ]
 
     operations = [
+        migrations.AlterModelOptions(
+            name='cable',
+            options={'ordering': ('pk',)},
+        ),
+        migrations.AlterUniqueTogether(
+            name='cable',
+            unique_together=set(),
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='termination_a_id',
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='termination_a_type',
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='termination_b_id',
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='termination_b_type',
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='_termination_a_device',
+        ),
+        migrations.RemoveField(
+            model_name='cable',
+            name='_termination_b_device',
+        ),
+        migrations.AlterUniqueTogether(
+            name='cablepath',
+            unique_together=set(),
+        ),
+        migrations.RemoveField(
+            model_name='cablepath',
+            name='destination_id',
+        ),
+        migrations.RemoveField(
+            model_name='cablepath',
+            name='destination_type',
+        ),
+        migrations.RemoveField(
+            model_name='cablepath',
+            name='origin_id',
+        ),
+        migrations.RemoveField(
+            model_name='cablepath',
+            name='origin_type',
+        ),
+        migrations.RemoveField(
+            model_name='consoleport',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='consoleport',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='consoleserverport',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='consoleserverport',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='frontport',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='frontport',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='interface',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='interface',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='powerfeed',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='powerfeed',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='poweroutlet',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='poweroutlet',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='powerport',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='powerport',
+            name='_link_peer_type',
+        ),
+        migrations.RemoveField(
+            model_name='rearport',
+            name='_link_peer_id',
+        ),
+        migrations.RemoveField(
+            model_name='rearport',
+            name='_link_peer_type',
+        ),
         migrations.RemoveConstraint(
             model_name='cabletermination',
             name='dcim_cable_termination_unique_termination',
@@ -329,4 +461,164 @@ class Migration(migrations.Migration):
             model_name='sitegroup',
             constraint=models.UniqueConstraint(condition=models.Q(('parent__isnull', True)), fields=('slug',), name='dcim_sitegroup_slug', violation_error_message='A top-level site group with this slug already exists.'),
         ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='weight',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='weight_unit',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='_abs_weight',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='moduletype',
+            name='weight',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
+        ),
+        migrations.AddField(
+            model_name='moduletype',
+            name='weight_unit',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='moduletype',
+            name='_abs_weight',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='weight',
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='max_weight',
+            field=models.PositiveIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='weight_unit',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='_abs_weight',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='_abs_max_weight',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='mounting_depth',
+            field=models.PositiveSmallIntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='cable',
+            name='comments',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AddField(
+            model_name='cable',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='module',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='moduletype',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='powerfeed',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='powerpanel',
+            name='comments',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AddField(
+            model_name='powerpanel',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.AddField(
+            model_name='rackreservation',
+            name='comments',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AddField(
+            model_name='virtualchassis',
+            name='comments',
+            field=models.TextField(blank=True),
+        ),
+        migrations.AddField(
+            model_name='virtualchassis',
+            name='description',
+            field=models.CharField(blank=True, max_length=200),
+        ),
+        migrations.CreateModel(
+            name='VirtualDeviceContext',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('name', models.CharField(max_length=64)),
+                ('status', models.CharField(max_length=50)),
+                ('identifier', models.PositiveSmallIntegerField(blank=True, null=True)),
+                ('comments', models.TextField(blank=True)),
+                ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='dcim.device')),
+                ('primary_ip4', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')),
+                ('primary_ip6', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+                ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='tenancy.tenant')),
+            ],
+            options={
+                'ordering': ['name'],
+            },
+        ),
+        migrations.AddField(
+            model_name='interface',
+            name='vdcs',
+            field=models.ManyToManyField(related_name='interfaces', to='dcim.virtualdevicecontext'),
+        ),
+        migrations.AddConstraint(
+            model_name='virtualdevicecontext',
+            constraint=models.UniqueConstraint(fields=('device', 'identifier'), name='dcim_virtualdevicecontext_device_identifier'),
+        ),
+        migrations.AddConstraint(
+            model_name='virtualdevicecontext',
+            constraint=models.UniqueConstraint(fields=('device', 'name'), name='dcim_virtualdevicecontext_device_name'),
+        ),
     ]

+ 0 - 134
netbox/dcim/migrations/0161_cabling_cleanup.py

@@ -1,134 +0,0 @@
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0160_populate_cable_ends'),
-    ]
-
-    operations = [
-
-        # Remove old fields from Cable
-        migrations.AlterModelOptions(
-            name='cable',
-            options={'ordering': ('pk',)},
-        ),
-        migrations.AlterUniqueTogether(
-            name='cable',
-            unique_together=set(),
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='termination_a_id',
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='termination_a_type',
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='termination_b_id',
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='termination_b_type',
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='_termination_a_device',
-        ),
-        migrations.RemoveField(
-            model_name='cable',
-            name='_termination_b_device',
-        ),
-
-        # Remove old fields from CablePath
-        migrations.AlterUniqueTogether(
-            name='cablepath',
-            unique_together=set(),
-        ),
-        migrations.RemoveField(
-            model_name='cablepath',
-            name='destination_id',
-        ),
-        migrations.RemoveField(
-            model_name='cablepath',
-            name='destination_type',
-        ),
-        migrations.RemoveField(
-            model_name='cablepath',
-            name='origin_id',
-        ),
-        migrations.RemoveField(
-            model_name='cablepath',
-            name='origin_type',
-        ),
-
-        # Remove link peer type/ID fields from cable termination models
-        migrations.RemoveField(
-            model_name='consoleport',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='consoleport',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='consoleserverport',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='consoleserverport',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='frontport',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='frontport',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='interface',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='interface',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='powerfeed',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='powerfeed',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='poweroutlet',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='poweroutlet',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='powerport',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='powerport',
-            name='_link_peer_type',
-        ),
-        migrations.RemoveField(
-            model_name='rearport',
-            name='_link_peer_id',
-        ),
-        migrations.RemoveField(
-            model_name='rearport',
-            name='_link_peer_type',
-        ),
-
-    ]

+ 0 - 72
netbox/dcim/migrations/0163_weight_fields.py

@@ -1,72 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0162_unique_constraints'),
-    ]
-
-    operations = [
-
-        # Device types
-        migrations.AddField(
-            model_name='devicetype',
-            name='weight',
-            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='weight_unit',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='_abs_weight',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-
-        # Module types
-        migrations.AddField(
-            model_name='moduletype',
-            name='weight',
-            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
-        ),
-        migrations.AddField(
-            model_name='moduletype',
-            name='weight_unit',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='moduletype',
-            name='_abs_weight',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-
-        # Racks
-        migrations.AddField(
-            model_name='rack',
-            name='weight',
-            field=models.DecimalField(blank=True, decimal_places=2, max_digits=8, null=True),
-        ),
-        migrations.AddField(
-            model_name='rack',
-            name='max_weight',
-            field=models.PositiveIntegerField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='rack',
-            name='weight_unit',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='rack',
-            name='_abs_weight',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='rack',
-            name='_abs_max_weight',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 18
netbox/dcim/migrations/0164_rack_mounting_depth.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.1.1 on 2022-10-27 14:01
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0163_weight_fields'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='rack',
-            name='mounting_depth',
-            field=models.PositiveSmallIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 78
netbox/dcim/migrations/0165_standardize_description_comments.py

@@ -1,78 +0,0 @@
-# Generated by Django 4.1.2 on 2022-11-03 18:24
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0164_rack_mounting_depth'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='cable',
-            name='comments',
-            field=models.TextField(blank=True),
-        ),
-        migrations.AddField(
-            model_name='cable',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='module',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='moduletype',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='powerfeed',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='powerpanel',
-            name='comments',
-            field=models.TextField(blank=True),
-        ),
-        migrations.AddField(
-            model_name='powerpanel',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='rack',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-        migrations.AddField(
-            model_name='rackreservation',
-            name='comments',
-            field=models.TextField(blank=True),
-        ),
-        migrations.AddField(
-            model_name='virtualchassis',
-            name='comments',
-            field=models.TextField(blank=True),
-        ),
-        migrations.AddField(
-            model_name='virtualchassis',
-            name='description',
-            field=models.CharField(blank=True, max_length=200),
-        ),
-    ]

+ 0 - 54
netbox/dcim/migrations/0166_virtualdevicecontext.py

@@ -1,54 +0,0 @@
-# Generated by Django 4.1.2 on 2022-11-10 16:56
-
-from django.db import migrations, models
-import django.db.models.deletion
-import taggit.managers
-import utilities.json
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('ipam', '0063_standardize_description_comments'),
-        ('extras', '0082_savedfilter'),
-        ('tenancy', '0009_standardize_description_comments'),
-        ('dcim', '0165_standardize_description_comments'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='VirtualDeviceContext',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('name', models.CharField(max_length=64)),
-                ('status', models.CharField(max_length=50)),
-                ('identifier', models.PositiveSmallIntegerField(blank=True, null=True)),
-                ('comments', models.TextField(blank=True)),
-                ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='dcim.device')),
-                ('primary_ip4', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')),
-                ('primary_ip6', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress')),
-                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
-                ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vdcs', to='tenancy.tenant')),
-            ],
-            options={
-                'ordering': ['name'],
-            },
-        ),
-        migrations.AddField(
-            model_name='interface',
-            name='vdcs',
-            field=models.ManyToManyField(related_name='interfaces', to='dcim.virtualdevicecontext'),
-        ),
-        migrations.AddConstraint(
-            model_name='virtualdevicecontext',
-            constraint=models.UniqueConstraint(fields=('device', 'identifier'), name='dcim_virtualdevicecontext_device_identifier'),
-        ),
-        migrations.AddConstraint(
-            model_name='virtualdevicecontext',
-            constraint=models.UniqueConstraint(fields=('device', 'name'), name='dcim_virtualdevicecontext_device_name'),
-        ),
-    ]

+ 0 - 18
netbox/dcim/migrations/0167_module_status.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.1.2 on 2022-12-09 15:09
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0166_virtualdevicecontext'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='module',
-            name='status',
-            field=models.CharField(default='active', max_length=50),
-        ),
-    ]

+ 251 - 0
netbox/dcim/migrations/0167_squashed_0182.py

@@ -0,0 +1,251 @@
+import django.core.validators
+import django.db.models.deletion
+from django.db import migrations, models
+
+import utilities.fields
+
+
+class Migration(migrations.Migration):
+
+    replaces = [
+        ('dcim', '0167_module_status'),
+        ('dcim', '0168_interface_template_enabled'),
+        ('dcim', '0169_devicetype_default_platform'),
+        ('dcim', '0170_configtemplate'),
+        ('dcim', '0171_cabletermination_change_logging'),
+        ('dcim', '0172_larger_power_draw_values'),
+        ('dcim', '0173_remove_napalm_fields'),
+        ('dcim', '0174_device_latitude_device_longitude'),
+        ('dcim', '0174_rack_starting_unit'),
+        ('dcim', '0175_device_oob_ip'),
+        ('dcim', '0176_device_component_counters'),
+        ('dcim', '0177_devicetype_component_counters'),
+        ('dcim', '0178_virtual_chassis_member_counter'),
+        ('dcim', '0179_interfacetemplate_rf_role'),
+        ('dcim', '0180_powerfeed_tenant'),
+        ('dcim', '0181_rename_device_role_device_role'),
+        ('dcim', '0182_zero_length_cable_fix')
+    ]
+
+    dependencies = [
+        ('extras', '0086_configtemplate'),
+        ('tenancy', '0010_tenant_relax_uniqueness'),
+        ('ipam', '0047_squashed_0053'),
+        ('dcim', '0166_virtualdevicecontext'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='module',
+            name='status',
+            field=models.CharField(default='active', max_length=50),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='enabled',
+            field=models.BooleanField(default=True),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='bridge',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interfacetemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='default_platform',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.platform'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='config_template',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='%(class)ss', to='extras.configtemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicerole',
+            name='config_template',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='device_roles', to='extras.configtemplate'),
+        ),
+        migrations.AddField(
+            model_name='platform',
+            name='config_template',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='platforms', to='extras.configtemplate'),
+        ),
+        migrations.AddField(
+            model_name='cabletermination',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='cabletermination',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='powerport',
+            name='allocated_draw',
+            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.AlterField(
+            model_name='powerport',
+            name='maximum_draw',
+            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.AlterField(
+            model_name='powerporttemplate',
+            name='allocated_draw',
+            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.AlterField(
+            model_name='powerporttemplate',
+            name='maximum_draw',
+            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.RemoveField(
+            model_name='platform',
+            name='napalm_args',
+        ),
+        migrations.RemoveField(
+            model_name='platform',
+            name='napalm_driver',
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='latitude',
+            field=models.DecimalField(blank=True, decimal_places=6, max_digits=8, null=True),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='longitude',
+            field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True),
+        ),
+        migrations.AddField(
+            model_name='rack',
+            name='starting_unit',
+            field=models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='oob_ip',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='ipam.ipaddress'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='console_port_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ConsolePort'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='console_server_port_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ConsoleServerPort'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='power_port_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.PowerPort'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='power_outlet_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.PowerOutlet'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='interface_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.Interface'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='front_port_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.FrontPort'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='rear_port_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.RearPort'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='device_bay_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.DeviceBay'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='module_bay_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.ModuleBay'),
+        ),
+        migrations.AddField(
+            model_name='device',
+            name='inventory_item_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device', to_model='dcim.InventoryItem'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='console_port_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ConsolePortTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='console_server_port_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ConsoleServerPortTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='power_port_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.PowerPortTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='power_outlet_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.PowerOutletTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='interface_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.InterfaceTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='front_port_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.FrontPortTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='rear_port_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.RearPortTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='device_bay_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.DeviceBayTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='module_bay_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.ModuleBayTemplate'),
+        ),
+        migrations.AddField(
+            model_name='devicetype',
+            name='inventory_item_template_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='device_type', to_model='dcim.InventoryItemTemplate'),
+        ),
+        migrations.AddField(
+            model_name='virtualchassis',
+            name='member_count',
+            field=utilities.fields.CounterCacheField(default=0, editable=False, to_field='virtual_chassis', to_model='dcim.Device'),
+        ),
+        migrations.AddField(
+            model_name='interfacetemplate',
+            name='rf_role',
+            field=models.CharField(blank=True, max_length=30),
+        ),
+        migrations.AddField(
+            model_name='powerfeed',
+            name='tenant',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='power_feeds', to='tenancy.tenant'),
+        ),
+        migrations.RenameField(
+            model_name='device',
+            old_name='device_role',
+            new_name='role',
+        ),
+    ]

+ 0 - 22
netbox/dcim/migrations/0168_interface_template_enabled.py

@@ -1,22 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0167_module_status'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='enabled',
-            field=models.BooleanField(default=True),
-        ),
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='bridge',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='bridge_interfaces', to='dcim.interfacetemplate'),
-        ),
-    ]

+ 0 - 19
netbox/dcim/migrations/0169_devicetype_default_platform.py

@@ -1,19 +0,0 @@
-# Generated by Django 4.1.6 on 2023-02-10 18:06
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0168_interface_template_enabled'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='devicetype',
-            name='default_platform',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.platform'),
-        ),
-    ]

+ 0 - 28
netbox/dcim/migrations/0170_configtemplate.py

@@ -1,28 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0086_configtemplate'),
-        ('dcim', '0169_devicetype_default_platform'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='device',
-            name='config_template',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='%(class)ss', to='extras.configtemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicerole',
-            name='config_template',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='device_roles', to='extras.configtemplate'),
-        ),
-        migrations.AddField(
-            model_name='platform',
-            name='config_template',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='platforms', to='extras.configtemplate'),
-        ),
-    ]

+ 0 - 21
netbox/dcim/migrations/0171_cabletermination_change_logging.py

@@ -1,21 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0170_configtemplate'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='cabletermination',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='cabletermination',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-    ]

+ 0 - 42
netbox/dcim/migrations/0172_larger_power_draw_values.py

@@ -1,42 +0,0 @@
-# Generated by Django 4.1.9 on 2023-05-12 18:46
-
-import django.core.validators
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0171_cabletermination_change_logging'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='powerport',
-            name='allocated_draw',
-            field=models.PositiveIntegerField(
-                blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]
-            ),
-        ),
-        migrations.AlterField(
-            model_name='powerport',
-            name='maximum_draw',
-            field=models.PositiveIntegerField(
-                blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]
-            ),
-        ),
-        migrations.AlterField(
-            model_name='powerporttemplate',
-            name='allocated_draw',
-            field=models.PositiveIntegerField(
-                blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]
-            ),
-        ),
-        migrations.AlterField(
-            model_name='powerporttemplate',
-            name='maximum_draw',
-            field=models.PositiveIntegerField(
-                blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]
-            ),
-        ),
-    ]

+ 0 - 19
netbox/dcim/migrations/0173_remove_napalm_fields.py

@@ -1,19 +0,0 @@
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0172_larger_power_draw_values'),
-    ]
-
-    operations = [
-        migrations.RemoveField(
-            model_name='platform',
-            name='napalm_args',
-        ),
-        migrations.RemoveField(
-            model_name='platform',
-            name='napalm_driver',
-        ),
-    ]

+ 0 - 22
netbox/dcim/migrations/0174_device_latitude_device_longitude.py

@@ -1,22 +0,0 @@
-# Generated by Django 4.1.9 on 2023-05-31 22:13
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('dcim', '0173_remove_napalm_fields'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='device',
-            name='latitude',
-            field=models.DecimalField(blank=True, decimal_places=6, max_digits=8, null=True),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='longitude',
-            field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True),
-        ),
-    ]

+ 0 - 18
netbox/dcim/migrations/0174_rack_starting_unit.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.1.9 on 2023-05-31 15:47
-
-import django.core.validators
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('dcim', '0174_device_latitude_device_longitude'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='rack',
-            name='starting_unit',
-            field=models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1)]),
-        ),
-    ]

+ 0 - 25
netbox/dcim/migrations/0175_device_oob_ip.py

@@ -1,25 +0,0 @@
-# Generated by Django 4.1.9 on 2023-07-24 20:29
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('ipam', '0066_iprange_mark_utilized'),
-        ('dcim', '0174_rack_starting_unit'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='device',
-            name='oob_ip',
-            field=models.OneToOneField(
-                blank=True,
-                null=True,
-                on_delete=django.db.models.deletion.SET_NULL,
-                related_name='+',
-                to='ipam.ipaddress',
-            ),
-        ),
-    ]

+ 0 - 83
netbox/dcim/migrations/0176_device_component_counters.py

@@ -1,83 +0,0 @@
-from django.db import migrations
-from django.db.models import Count
-
-import utilities.fields
-from utilities.counters import update_counts
-
-
-def recalculate_device_counts(apps, schema_editor):
-    Device = apps.get_model("dcim", "Device")
-
-    update_counts(Device, 'console_port_count', 'consoleports')
-    update_counts(Device, 'console_server_port_count', 'consoleserverports')
-    update_counts(Device, 'power_port_count', 'powerports')
-    update_counts(Device, 'power_outlet_count', 'poweroutlets')
-    update_counts(Device, 'interface_count', 'interfaces')
-    update_counts(Device, 'front_port_count', 'frontports')
-    update_counts(Device, 'rear_port_count', 'rearports')
-    update_counts(Device, 'device_bay_count', 'devicebays')
-    update_counts(Device, 'module_bay_count', 'modulebays')
-    update_counts(Device, 'inventory_item_count', 'inventoryitems')
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('dcim', '0175_device_oob_ip'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='device',
-            name='console_port_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.ConsolePort'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='console_server_port_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.ConsoleServerPort'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='power_port_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.PowerPort'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='power_outlet_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.PowerOutlet'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='interface_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.Interface'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='front_port_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.FrontPort'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='rear_port_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.RearPort'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='device_bay_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.DeviceBay'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='module_bay_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.ModuleBay'),
-        ),
-        migrations.AddField(
-            model_name='device',
-            name='inventory_item_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device', to_model='dcim.InventoryItem'),
-        ),
-        migrations.RunPython(
-            recalculate_device_counts,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 83
netbox/dcim/migrations/0177_devicetype_component_counters.py

@@ -1,83 +0,0 @@
-from django.db import migrations
-from django.db.models import Count
-
-import utilities.fields
-from utilities.counters import update_counts
-
-
-def recalculate_devicetype_template_counts(apps, schema_editor):
-    DeviceType = apps.get_model("dcim", "DeviceType")
-
-    update_counts(DeviceType, 'console_port_template_count', 'consoleporttemplates')
-    update_counts(DeviceType, 'console_server_port_template_count', 'consoleserverporttemplates')
-    update_counts(DeviceType, 'power_port_template_count', 'powerporttemplates')
-    update_counts(DeviceType, 'power_outlet_template_count', 'poweroutlettemplates')
-    update_counts(DeviceType, 'interface_template_count', 'interfacetemplates')
-    update_counts(DeviceType, 'front_port_template_count', 'frontporttemplates')
-    update_counts(DeviceType, 'rear_port_template_count', 'rearporttemplates')
-    update_counts(DeviceType, 'device_bay_template_count', 'devicebaytemplates')
-    update_counts(DeviceType, 'module_bay_template_count', 'modulebaytemplates')
-    update_counts(DeviceType, 'inventory_item_template_count', 'inventoryitemtemplates')
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('dcim', '0176_device_component_counters'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='devicetype',
-            name='console_port_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.ConsolePortTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='console_server_port_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.ConsoleServerPortTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='power_port_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.PowerPortTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='power_outlet_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.PowerOutletTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='interface_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.InterfaceTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='front_port_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.FrontPortTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='rear_port_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.RearPortTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='device_bay_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.DeviceBayTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='module_bay_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.ModuleBayTemplate'),
-        ),
-        migrations.AddField(
-            model_name='devicetype',
-            name='inventory_item_template_count',
-            field=utilities.fields.CounterCacheField(default=0, to_field='device_type', to_model='dcim.InventoryItemTemplate'),
-        ),
-        migrations.RunPython(
-            recalculate_devicetype_template_counts,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 31
netbox/dcim/migrations/0178_virtual_chassis_member_counter.py

@@ -1,31 +0,0 @@
-from django.db import migrations
-from django.db.models import Count
-
-import utilities.fields
-from utilities.counters import update_counts
-
-
-def populate_virtualchassis_members(apps, schema_editor):
-    VirtualChassis = apps.get_model('dcim', 'VirtualChassis')
-
-    update_counts(VirtualChassis, 'member_count', 'members')
-
-
-class Migration(migrations.Migration):
-    dependencies = [
-        ('dcim', '0177_devicetype_component_counters'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='virtualchassis',
-            name='member_count',
-            field=utilities.fields.CounterCacheField(
-                default=0, to_field='virtual_chassis', to_model='dcim.Device'
-            ),
-        ),
-        migrations.RunPython(
-            code=populate_virtualchassis_members,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 18
netbox/dcim/migrations/0179_interfacetemplate_rf_role.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.2.2 on 2023-07-18 07:55
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0178_virtual_chassis_member_counter'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='interfacetemplate',
-            name='rf_role',
-            field=models.CharField(blank=True, max_length=30),
-        ),
-    ]

+ 0 - 20
netbox/dcim/migrations/0180_powerfeed_tenant.py

@@ -1,20 +0,0 @@
-# Generated by Django 4.1.8 on 2023-07-29 11:29
-
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('tenancy', '0010_tenant_relax_uniqueness'),
-        ('dcim', '0179_interfacetemplate_rf_role'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='powerfeed',
-            name='tenant',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='power_feeds', to='tenancy.tenant'),
-        ),
-    ]

+ 0 - 35
netbox/dcim/migrations/0181_rename_device_role_device_role.py

@@ -1,35 +0,0 @@
-from django.db import migrations
-
-
-def update_table_configs(apps, schema_editor):
-    """
-    Replace the `device_role` column in DeviceTable configs with `role`.
-    """
-    UserConfig = apps.get_model('users', 'UserConfig')
-
-    for table in ('DeviceTable', 'DeviceBayTable'):
-        for config in UserConfig.objects.filter(**{f'data__tables__{table}__columns__contains': 'device_role'}):
-            config.data['tables'][table]['columns'] = [
-                'role' if x == 'device_role' else x
-                for x in config.data['tables'][table]['columns']
-            ]
-            config.save()
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0180_powerfeed_tenant'),
-    ]
-
-    operations = [
-        migrations.RenameField(
-            model_name='device',
-            old_name='device_role',
-            new_name='role',
-        ),
-        migrations.RunPython(
-            code=update_table_configs,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 22
netbox/dcim/migrations/0182_zero_length_cable_fix.py

@@ -1,22 +0,0 @@
-from django.db import migrations
-
-
-def update_cable_lengths(apps, schema_editor):
-    Cable = apps.get_model('dcim', 'Cable')
-
-    # Set the absolute length for any zero-length Cables
-    Cable.objects.filter(length=0).update(_abs_length=0)
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0181_rename_device_role_device_role'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=update_cable_lengths,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 16
netbox/extras/migrations/0060_customlink_button_class.py

@@ -1,16 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0059_exporttemplate_as_attachment'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='customlink',
-            name='button_class',
-            field=models.CharField(default='outline-dark', max_length=30),
-        ),
-    ]

+ 510 - 0
netbox/extras/migrations/0060_squashed_0086.py

@@ -0,0 +1,510 @@
+import re
+import uuid
+
+import django.core.validators
+import django.db.models.deletion
+import taggit.managers
+from django.conf import settings
+from django.db import migrations, models
+
+import extras.fields
+import utilities.json
+
+
+class Migration(migrations.Migration):
+
+    replaces = [
+        ('extras', '0060_customlink_button_class'),
+        ('extras', '0061_extras_change_logging'),
+        ('extras', '0062_clear_secrets_changelog'),
+        ('extras', '0063_webhook_conditions'),
+        ('extras', '0064_configrevision'),
+        ('extras', '0065_imageattachment_change_logging'),
+        ('extras', '0066_customfield_name_validation'),
+        ('extras', '0067_customfield_min_max_values'),
+        ('extras', '0068_configcontext_cluster_types'),
+        ('extras', '0069_custom_object_field'),
+        ('extras', '0070_customlink_enabled'),
+        ('extras', '0071_standardize_id_fields'),
+        ('extras', '0072_created_datetimefield'),
+        ('extras', '0073_journalentry_tags_custom_fields'),
+        ('extras', '0074_customfield_extensions'),
+        ('extras', '0075_configcontext_locations'),
+        ('extras', '0076_tag_slug_unicode'),
+        ('extras', '0077_customlink_extend_text_and_url'),
+        ('extras', '0078_unique_constraints'),
+        ('extras', '0079_scheduled_jobs'),
+        ('extras', '0080_customlink_content_types'),
+        ('extras', '0081_exporttemplate_content_types'),
+        ('extras', '0082_savedfilter'),
+        ('extras', '0083_search'),
+        ('extras', '0084_staging'),
+        ('extras', '0085_synced_data'),
+        ('extras', '0086_configtemplate')
+    ]
+
+    dependencies = [
+        ('virtualization', '0001_squashed_0022'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('core', '0001_initial'),
+        ('contenttypes', '0002_remove_content_type_name'),
+        ('wireless', '0008_wirelesslan_status'),
+        ('dcim', '0166_virtualdevicecontext'),
+        ('tenancy', '0009_standardize_description_comments'),
+        ('extras', '0059_exporttemplate_as_attachment'),
+        ('circuits', '0041_standardize_description_comments'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='customlink',
+            name='button_class',
+            field=models.CharField(default='outline-dark', max_length=30),
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='created',
+            field=models.DateField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='customlink',
+            name='created',
+            field=models.DateField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='customlink',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='created',
+            field=models.DateField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='webhook',
+            name='created',
+            field=models.DateField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='webhook',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='webhook',
+            name='conditions',
+            field=models.JSONField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='imageattachment',
+            name='last_updated',
+            field=models.DateTimeField(auto_now=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='customfield',
+            name='name',
+            field=models.CharField(max_length=50, unique=True, validators=[django.core.validators.RegexValidator(flags=re.RegexFlag['IGNORECASE'], message='Only alphanumeric characters and underscores are allowed.', regex='^[a-z0-9_]+$'), django.core.validators.RegexValidator(flags=re.RegexFlag['IGNORECASE'], inverse_match=True, message='Double underscores are not permitted in custom field names.', regex='__')]),
+        ),
+        migrations.AlterField(
+            model_name='customfield',
+            name='validation_maximum',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='customfield',
+            name='validation_minimum',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='cluster_types',
+            field=models.ManyToManyField(blank=True, related_name='+', to='virtualization.clustertype'),
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='object_type',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'),
+        ),
+        migrations.AddField(
+            model_name='customlink',
+            name='enabled',
+            field=models.BooleanField(default=True),
+        ),
+        migrations.AlterField(
+            model_name='configcontext',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.CreateModel(
+            name='ConfigRevision',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True)),
+                ('comment', models.CharField(blank=True, max_length=200)),
+                ('data', models.JSONField(blank=True, null=True)),
+            ],
+        ),
+        migrations.AlterField(
+            model_name='customfield',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='customlink',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='exporttemplate',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='imageattachment',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='jobresult',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='journalentry',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='objectchange',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='taggeditem',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='webhook',
+            name='id',
+            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
+        ),
+        migrations.AlterField(
+            model_name='imageattachment',
+            name='object_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='journalentry',
+            name='assigned_object_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='objectchange',
+            name='changed_object_id',
+            field=models.PositiveBigIntegerField(),
+        ),
+        migrations.AlterField(
+            model_name='objectchange',
+            name='related_object_id',
+            field=models.PositiveBigIntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='configcontext',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='customfield',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='customlink',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='exporttemplate',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='imageattachment',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='journalentry',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='tag',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='webhook',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='journalentry',
+            name='custom_field_data',
+            field=models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder),
+        ),
+        migrations.AddField(
+            model_name='journalentry',
+            name='tags',
+            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
+        ),
+        migrations.AlterModelOptions(
+            name='customfield',
+            options={'ordering': ['group_name', 'weight', 'name']},
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='group_name',
+            field=models.CharField(blank=True, max_length=50),
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='ui_visibility',
+            field=models.CharField(default='read-write', max_length=50),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='locations',
+            field=models.ManyToManyField(blank=True, related_name='+', to='dcim.location'),
+        ),
+        migrations.AlterField(
+            model_name='tag',
+            name='slug',
+            field=models.SlugField(allow_unicode=True, max_length=100, unique=True),
+        ),
+        migrations.AlterField(
+            model_name='customlink',
+            name='link_text',
+            field=models.TextField(),
+        ),
+        migrations.AlterField(
+            model_name='customlink',
+            name='link_url',
+            field=models.TextField(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='exporttemplate',
+            unique_together=set(),
+        ),
+        migrations.AlterUniqueTogether(
+            name='webhook',
+            unique_together=set(),
+        ),
+        migrations.AddConstraint(
+            model_name='exporttemplate',
+            constraint=models.UniqueConstraint(fields=('content_type', 'name'), name='extras_exporttemplate_unique_content_type_name'),
+        ),
+        migrations.AddConstraint(
+            model_name='webhook',
+            constraint=models.UniqueConstraint(fields=('payload_url', 'type_create', 'type_update', 'type_delete'), name='extras_webhook_unique_payload_url_types'),
+        ),
+        migrations.AddField(
+            model_name='jobresult',
+            name='scheduled',
+            field=models.DateTimeField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='jobresult',
+            name='interval',
+            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
+        ),
+        migrations.AddField(
+            model_name='jobresult',
+            name='started',
+            field=models.DateTimeField(blank=True, null=True),
+        ),
+        migrations.AlterModelOptions(
+            name='jobresult',
+            options={'ordering': ['-created']},
+        ),
+        migrations.AddField(
+            model_name='customlink',
+            name='content_types',
+            field=models.ManyToManyField(related_name='custom_links', to='contenttypes.contenttype'),
+        ),
+        migrations.RemoveField(
+            model_name='customlink',
+            name='content_type',
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='content_types',
+            field=models.ManyToManyField(related_name='export_templates', to='contenttypes.contenttype'),
+        ),
+        migrations.RemoveConstraint(
+            model_name='exporttemplate',
+            name='extras_exporttemplate_unique_content_type_name',
+        ),
+        migrations.RemoveField(
+            model_name='exporttemplate',
+            name='content_type',
+        ),
+        migrations.AlterModelOptions(
+            name='exporttemplate',
+            options={'ordering': ('name',)},
+        ),
+        migrations.CreateModel(
+            name='SavedFilter',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('name', models.CharField(max_length=100, unique=True)),
+                ('slug', models.SlugField(max_length=100, unique=True)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('weight', models.PositiveSmallIntegerField(default=100)),
+                ('enabled', models.BooleanField(default=True)),
+                ('shared', models.BooleanField(default=True)),
+                ('parameters', models.JSONField()),
+                ('content_types', models.ManyToManyField(related_name='saved_filters', to='contenttypes.contenttype')),
+                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'ordering': ('weight', 'name'),
+            },
+        ),
+        migrations.AddField(
+            model_name='customfield',
+            name='search_weight',
+            field=models.PositiveSmallIntegerField(default=1000),
+        ),
+        migrations.CreateModel(
+            name='CachedValue',
+            fields=[
+                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('timestamp', models.DateTimeField(auto_now_add=True)),
+                ('object_id', models.PositiveBigIntegerField()),
+                ('field', models.CharField(max_length=200)),
+                ('type', models.CharField(max_length=30)),
+                ('value', extras.fields.CachedValueField()),
+                ('weight', models.PositiveSmallIntegerField(default=1000)),
+                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
+            ],
+            options={
+                'ordering': ('weight', 'object_type', 'object_id'),
+            },
+        ),
+        migrations.CreateModel(
+            name='Branch',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('name', models.CharField(max_length=100, unique=True)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'ordering': ('name',),
+            },
+        ),
+        migrations.CreateModel(
+            name='StagedChange',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('action', models.CharField(max_length=20)),
+                ('object_id', models.PositiveBigIntegerField(blank=True, null=True)),
+                ('data', models.JSONField(blank=True, null=True)),
+                ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staged_changes', to='extras.branch')),
+                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
+            ],
+            options={
+                'ordering': ('pk',),
+            },
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='data_file',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile'),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='data_path',
+            field=models.CharField(blank=True, editable=False, max_length=1000),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='data_source',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource'),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='auto_sync_enabled',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddField(
+            model_name='configcontext',
+            name='data_synced',
+            field=models.DateTimeField(blank=True, editable=False, null=True),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='data_file',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile'),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='data_path',
+            field=models.CharField(blank=True, editable=False, max_length=1000),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='data_source',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource'),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='auto_sync_enabled',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddField(
+            model_name='exporttemplate',
+            name='data_synced',
+            field=models.DateTimeField(blank=True, editable=False, null=True),
+        ),
+        migrations.CreateModel(
+            name='ConfigTemplate',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
+                ('created', models.DateTimeField(auto_now_add=True, null=True)),
+                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
+                ('data_path', models.CharField(blank=True, editable=False, max_length=1000)),
+                ('data_synced', models.DateTimeField(blank=True, editable=False, null=True)),
+                ('name', models.CharField(max_length=100)),
+                ('description', models.CharField(blank=True, max_length=200)),
+                ('template_code', models.TextField()),
+                ('environment_params', models.JSONField(blank=True, default=dict, null=True)),
+                ('data_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='core.datafile')),
+                ('data_source', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='core.datasource')),
+                ('auto_sync_enabled', models.BooleanField(default=False)),
+                ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
+            ],
+            options={
+                'ordering': ('name',),
+            },
+        ),
+    ]

+ 0 - 51
netbox/extras/migrations/0061_extras_change_logging.py

@@ -1,51 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0060_customlink_button_class'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='customfield',
-            name='created',
-            field=models.DateField(auto_now_add=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='customfield',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='customlink',
-            name='created',
-            field=models.DateField(auto_now_add=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='customlink',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='exporttemplate',
-            name='created',
-            field=models.DateField(auto_now_add=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='exporttemplate',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='webhook',
-            name='created',
-            field=models.DateField(auto_now_add=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='webhook',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-    ]

+ 0 - 26
netbox/extras/migrations/0062_clear_secrets_changelog.py

@@ -1,26 +0,0 @@
-from django.db import migrations
-
-
-def clear_secrets_changelog(apps, schema_editor):
-    """
-    Delete all ObjectChange records referencing a model within the old secrets app (pre-v3.0).
-    """
-    ContentType = apps.get_model('contenttypes', 'ContentType')
-    ObjectChange = apps.get_model('extras', 'ObjectChange')
-
-    content_type_ids = ContentType.objects.filter(app_label='secrets').values_list('id', flat=True)
-    ObjectChange.objects.filter(changed_object_type__in=content_type_ids).delete()
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0061_extras_change_logging'),
-    ]
-
-    operations = [
-        migrations.RunPython(
-            code=clear_secrets_changelog,
-            reverse_code=migrations.RunPython.noop
-        ),
-    ]

+ 0 - 18
netbox/extras/migrations/0063_webhook_conditions.py

@@ -1,18 +0,0 @@
-# Generated by Django 3.2.8 on 2021-10-22 20:37
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0062_clear_secrets_changelog'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='webhook',
-            name='conditions',
-            field=models.JSONField(blank=True, null=True),
-        ),
-    ]

+ 0 - 20
netbox/extras/migrations/0064_configrevision.py

@@ -1,20 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0063_webhook_conditions'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='ConfigRevision',
-            fields=[
-                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('created', models.DateTimeField(auto_now_add=True)),
-                ('comment', models.CharField(blank=True, max_length=200)),
-                ('data', models.JSONField(blank=True, null=True)),
-            ],
-        ),
-    ]

+ 0 - 16
netbox/extras/migrations/0065_imageattachment_change_logging.py

@@ -1,16 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0064_configrevision'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='imageattachment',
-            name='last_updated',
-            field=models.DateTimeField(auto_now=True, null=True),
-        ),
-    ]

+ 0 - 34
netbox/extras/migrations/0066_customfield_name_validation.py

@@ -1,34 +0,0 @@
-import django.core.validators
-from django.db import migrations, models
-import re
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0065_imageattachment_change_logging'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='customfield',
-            name='name',
-            field=models.CharField(
-                max_length=50,
-                unique=True,
-                validators=[
-                    django.core.validators.RegexValidator(
-                        flags=re.RegexFlag['IGNORECASE'],
-                        message='Only alphanumeric characters and underscores are allowed.',
-                        regex='^[a-z0-9_]+$',
-                    ),
-                    django.core.validators.RegexValidator(
-                        flags=re.RegexFlag['IGNORECASE'],
-                        inverse_match=True,
-                        message='Double underscores are not permitted in custom field names.',
-                        regex=r'__',
-                    ),
-                ],
-            ),
-        ),
-    ]

+ 0 - 21
netbox/extras/migrations/0067_customfield_min_max_values.py

@@ -1,21 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0066_customfield_name_validation'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='customfield',
-            name='validation_maximum',
-            field=models.IntegerField(blank=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='customfield',
-            name='validation_minimum',
-            field=models.IntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 18
netbox/extras/migrations/0068_configcontext_cluster_types.py

@@ -1,18 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0145_site_remove_deprecated_fields'),
-        ('virtualization', '0026_vminterface_bridge'),
-        ('extras', '0067_customfield_min_max_values'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='configcontext',
-            name='cluster_types',
-            field=models.ManyToManyField(blank=True, related_name='+', to='virtualization.ClusterType'),
-        ),
-    ]

+ 0 - 18
netbox/extras/migrations/0069_custom_object_field.py

@@ -1,18 +0,0 @@
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('extras', '0068_configcontext_cluster_types'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='customfield',
-            name='object_type',
-            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='contenttypes.contenttype'),
-        ),
-    ]

+ 0 - 18
netbox/extras/migrations/0070_customlink_enabled.py

@@ -1,18 +0,0 @@
-# Generated by Django 3.2.11 on 2022-01-10 16:45
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0069_custom_object_field'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='customlink',
-            name='enabled',
-            field=models.BooleanField(default=True),
-        ),
-    ]

+ 0 - 89
netbox/extras/migrations/0071_standardize_id_fields.py

@@ -1,89 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0070_customlink_enabled'),
-    ]
-
-    operations = [
-        # Model IDs
-        migrations.AlterField(
-            model_name='configcontext',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='configrevision',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='customfield',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='customlink',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='exporttemplate',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='imageattachment',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='jobresult',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='journalentry',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='objectchange',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='taggeditem',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-        migrations.AlterField(
-            model_name='webhook',
-            name='id',
-            field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False),
-        ),
-
-        # GFK IDs
-        migrations.AlterField(
-            model_name='imageattachment',
-            name='object_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='journalentry',
-            name='assigned_object_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='objectchange',
-            name='changed_object_id',
-            field=models.PositiveBigIntegerField(),
-        ),
-        migrations.AlterField(
-            model_name='objectchange',
-            name='related_object_id',
-            field=models.PositiveBigIntegerField(blank=True, null=True),
-        ),
-    ]

+ 0 - 53
netbox/extras/migrations/0072_created_datetimefield.py

@@ -1,53 +0,0 @@
-# Generated by Django 4.0.2 on 2022-02-08 18:54
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0071_standardize_id_fields'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='configcontext',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='customfield',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='customlink',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='exporttemplate',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='imageattachment',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='journalentry',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='tag',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-        migrations.AlterField(
-            model_name='webhook',
-            name='created',
-            field=models.DateTimeField(auto_now_add=True, null=True),
-        ),
-    ]

+ 0 - 23
netbox/extras/migrations/0073_journalentry_tags_custom_fields.py

@@ -1,23 +0,0 @@
-from utilities.json import CustomFieldJSONEncoder
-from django.db import migrations, models
-import taggit.managers
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0072_created_datetimefield'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='journalentry',
-            name='custom_field_data',
-            field=models.JSONField(blank=True, default=dict, encoder=CustomFieldJSONEncoder),
-        ),
-        migrations.AddField(
-            model_name='journalentry',
-            name='tags',
-            field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
-        ),
-    ]

+ 0 - 27
netbox/extras/migrations/0074_customfield_extensions.py

@@ -1,27 +0,0 @@
-# Generated by Django 4.0.4 on 2022-04-15 17:13
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0073_journalentry_tags_custom_fields'),
-    ]
-
-    operations = [
-        migrations.AlterModelOptions(
-            name='customfield',
-            options={'ordering': ['group_name', 'weight', 'name']},
-        ),
-        migrations.AddField(
-            model_name='customfield',
-            name='group_name',
-            field=models.CharField(blank=True, max_length=50),
-        ),
-        migrations.AddField(
-            model_name='customfield',
-            name='ui_visibility',
-            field=models.CharField(default='read-write', max_length=50),
-        ),
-    ]

+ 0 - 19
netbox/extras/migrations/0075_configcontext_locations.py

@@ -1,19 +0,0 @@
-# Generated by Django 4.0.5 on 2022-06-22 19:13
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('dcim', '0156_location_status'),
-        ('extras', '0074_customfield_extensions'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='configcontext',
-            name='locations',
-            field=models.ManyToManyField(blank=True, related_name='+', to='dcim.location'),
-        ),
-    ]

+ 0 - 18
netbox/extras/migrations/0076_tag_slug_unicode.py

@@ -1,18 +0,0 @@
-# Generated by Django 4.0.6 on 2022-07-14 15:51
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0075_configcontext_locations'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='tag',
-            name='slug',
-            field=models.SlugField(allow_unicode=True, max_length=100, unique=True),
-        ),
-    ]

+ 0 - 21
netbox/extras/migrations/0077_customlink_extend_text_and_url.py

@@ -1,21 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0076_tag_slug_unicode'),
-    ]
-
-    operations = [
-        migrations.AlterField(
-            model_name='customlink',
-            name='link_text',
-            field=models.TextField(),
-        ),
-        migrations.AlterField(
-            model_name='customlink',
-            name='link_url',
-            field=models.TextField(),
-        ),
-    ]

+ 0 - 27
netbox/extras/migrations/0078_unique_constraints.py

@@ -1,27 +0,0 @@
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0077_customlink_extend_text_and_url'),
-    ]
-
-    operations = [
-        migrations.AlterUniqueTogether(
-            name='exporttemplate',
-            unique_together=set(),
-        ),
-        migrations.AlterUniqueTogether(
-            name='webhook',
-            unique_together=set(),
-        ),
-        migrations.AddConstraint(
-            model_name='exporttemplate',
-            constraint=models.UniqueConstraint(fields=('content_type', 'name'), name='extras_exporttemplate_unique_content_type_name'),
-        ),
-        migrations.AddConstraint(
-            model_name='webhook',
-            constraint=models.UniqueConstraint(fields=('payload_url', 'type_create', 'type_update', 'type_delete'), name='extras_webhook_unique_payload_url_types'),
-        ),
-    ]

+ 0 - 31
netbox/extras/migrations/0079_scheduled_jobs.py

@@ -1,31 +0,0 @@
-import django.core.validators
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('extras', '0078_unique_constraints'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='jobresult',
-            name='scheduled',
-            field=models.DateTimeField(blank=True, null=True),
-        ),
-        migrations.AddField(
-            model_name='jobresult',
-            name='interval',
-            field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]),
-        ),
-        migrations.AddField(
-            model_name='jobresult',
-            name='started',
-            field=models.DateTimeField(blank=True, null=True),
-        ),
-        migrations.AlterModelOptions(
-            name='jobresult',
-            options={'ordering': ['-created']},
-        ),
-    ]

+ 0 - 32
netbox/extras/migrations/0080_customlink_content_types.py

@@ -1,32 +0,0 @@
-from django.db import migrations, models
-
-
-def copy_content_types(apps, schema_editor):
-    CustomLink = apps.get_model('extras', 'CustomLink')
-
-    for customlink in CustomLink.objects.all():
-        customlink.content_types.set([customlink.content_type])
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('extras', '0079_scheduled_jobs'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='customlink',
-            name='content_types',
-            field=models.ManyToManyField(related_name='custom_links', to='contenttypes.contenttype'),
-        ),
-        migrations.RunPython(
-            code=copy_content_types,
-            reverse_code=migrations.RunPython.noop
-        ),
-        migrations.RemoveField(
-            model_name='customlink',
-            name='content_type',
-        ),
-    ]

+ 0 - 40
netbox/extras/migrations/0081_exporttemplate_content_types.py

@@ -1,40 +0,0 @@
-from django.db import migrations, models
-
-
-def copy_content_types(apps, schema_editor):
-    ExportTemplate = apps.get_model('extras', 'ExportTemplate')
-
-    for et in ExportTemplate.objects.all():
-        et.content_types.set([et.content_type])
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('extras', '0080_customlink_content_types'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='exporttemplate',
-            name='content_types',
-            field=models.ManyToManyField(related_name='export_templates', to='contenttypes.contenttype'),
-        ),
-        migrations.RunPython(
-            code=copy_content_types,
-            reverse_code=migrations.RunPython.noop
-        ),
-        migrations.RemoveConstraint(
-            model_name='exporttemplate',
-            name='extras_exporttemplate_unique_content_type_name',
-        ),
-        migrations.RemoveField(
-            model_name='exporttemplate',
-            name='content_type',
-        ),
-        migrations.AlterModelOptions(
-            name='exporttemplate',
-            options={'ordering': ('name',)},
-        ),
-    ]

+ 0 - 35
netbox/extras/migrations/0082_savedfilter.py

@@ -1,35 +0,0 @@
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('extras', '0081_exporttemplate_content_types'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='SavedFilter',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('name', models.CharField(max_length=100, unique=True)),
-                ('slug', models.SlugField(max_length=100, unique=True)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('weight', models.PositiveSmallIntegerField(default=100)),
-                ('enabled', models.BooleanField(default=True)),
-                ('shared', models.BooleanField(default=True)),
-                ('parameters', models.JSONField()),
-                ('content_types', models.ManyToManyField(related_name='saved_filters', to='contenttypes.contenttype')),
-                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'ordering': ('weight', 'name'),
-            },
-        ),
-    ]

+ 0 - 44
netbox/extras/migrations/0083_search.py

@@ -1,44 +0,0 @@
-import uuid
-
-import django.db.models.deletion
-import django.db.models.lookups
-from django.db import migrations, models
-import extras.fields
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('circuits', '0041_standardize_description_comments'),
-        ('contenttypes', '0002_remove_content_type_name'),
-        ('dcim', '0166_virtualdevicecontext'),
-        ('extras', '0082_savedfilter'),
-        ('ipam', '0063_standardize_description_comments'),
-        ('tenancy', '0009_standardize_description_comments'),
-        ('virtualization', '0034_standardize_description_comments'),
-        ('wireless', '0008_wirelesslan_status'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='customfield',
-            name='search_weight',
-            field=models.PositiveSmallIntegerField(default=1000),
-        ),
-        migrations.CreateModel(
-            name='CachedValue',
-            fields=[
-                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
-                ('timestamp', models.DateTimeField(auto_now_add=True)),
-                ('object_id', models.PositiveBigIntegerField()),
-                ('field', models.CharField(max_length=200)),
-                ('type', models.CharField(max_length=30)),
-                ('value', extras.fields.CachedValueField()),
-                ('weight', models.PositiveSmallIntegerField(default=1000)),
-                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
-            ],
-            options={
-                'ordering': ('weight', 'object_type', 'object_id'),
-            },
-        ),
-    ]

+ 0 - 45
netbox/extras/migrations/0084_staging.py

@@ -1,45 +0,0 @@
-from django.conf import settings
-from django.db import migrations, models
-import django.db.models.deletion
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('contenttypes', '0002_remove_content_type_name'),
-        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
-        ('extras', '0083_search'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Branch',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('name', models.CharField(max_length=100, unique=True)),
-                ('description', models.CharField(blank=True, max_length=200)),
-                ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
-            ],
-            options={
-                'ordering': ('name',),
-            },
-        ),
-        migrations.CreateModel(
-            name='StagedChange',
-            fields=[
-                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
-                ('created', models.DateTimeField(auto_now_add=True, null=True)),
-                ('last_updated', models.DateTimeField(auto_now=True, null=True)),
-                ('action', models.CharField(max_length=20)),
-                ('object_id', models.PositiveBigIntegerField(blank=True, null=True)),
-                ('data', models.JSONField(blank=True, null=True)),
-                ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staged_changes', to='extras.branch')),
-                ('object_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='contenttypes.contenttype')),
-            ],
-            options={
-                'ordering': ('pk',),
-            },
-        ),
-    ]

Некоторые файлы не были показаны из-за большого количества измененных файлов