From 7e6cb9d18696eb312954796cda22f19fd1b51c7c Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 26 Feb 2021 16:12:52 -0500 Subject: [PATCH] Closes #1638: Migrate all primary keys to 64-bit integers --- docs/release-notes/index.md | 2 +- docs/release-notes/version-2.11.md | 9 + .../migrations/0025_standardize_models.py | 8 +- .../migrations/0123_standardize_models.py | 288 +----------------- .../dcim/models/device_component_templates.py | 4 +- netbox/dcim/models/device_components.py | 4 +- .../migrations/0054_standardize_models.py | 8 +- netbox/extras/models/models.py | 4 +- netbox/extras/models/tags.py | 4 +- .../migrations/0044_standardize_models.py | 18 +- netbox/netbox/models.py | 54 ++-- .../migrations/0013_standardize_models.py | 8 +- .../migrations/0012_standardize_models.py | 8 +- .../migrations/0011_standardize_models.py | 7 +- netbox/users/models.py | 2 +- .../migrations/0020_standardize_models.py | 28 +- netbox/virtualization/models.py | 4 +- 17 files changed, 72 insertions(+), 388 deletions(-) create mode 100644 docs/release-notes/version-2.11.md diff --git a/docs/release-notes/index.md b/docs/release-notes/index.md index 8990f83e0..f7f6f36e9 120000 --- a/docs/release-notes/index.md +++ b/docs/release-notes/index.md @@ -1 +1 @@ -version-2.10.md \ No newline at end of file +version-2.11.md \ No newline at end of file diff --git a/docs/release-notes/version-2.11.md b/docs/release-notes/version-2.11.md new file mode 100644 index 000000000..4daeab8bc --- /dev/null +++ b/docs/release-notes/version-2.11.md @@ -0,0 +1,9 @@ +# NetBox v2.11 + +## v2.11-beta1 (FUTURE) + +**WARNING:** This is a beta release and is not suitable for production use. It is intended for development and evaluation purposes only. No upgrade path to the final v2.11 release will be provided from this beta, and users should assume that all data entered into the application will be lost. + +### Other Changes + +* [#1638](https://github.com/netbox-community/netbox/issues/1638) - Migrate all primary keys to 64-bit integers diff --git a/netbox/circuits/migrations/0025_standardize_models.py b/netbox/circuits/migrations/0025_standardize_models.py index 2b1d2664e..f5d348ff3 100644 --- a/netbox/circuits/migrations/0025_standardize_models.py +++ b/netbox/circuits/migrations/0025_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,11 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='circuittype', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='circuit', name='id', diff --git a/netbox/dcim/migrations/0123_standardize_models.py b/netbox/dcim/migrations/0123_standardize_models.py index 5050e1a26..e9af8c464 100644 --- a/netbox/dcim/migrations/0123_standardize_models.py +++ b/netbox/dcim/migrations/0123_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,291 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='consoleport', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='consoleport', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='consoleport', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='consoleporttemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='consoleporttemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='consoleporttemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='consoleserverport', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='consoleserverport', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='consoleserverport', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='consoleserverporttemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='consoleserverporttemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='consoleserverporttemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='devicebay', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='devicebay', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='devicebay', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='devicebaytemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='devicebaytemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='devicebaytemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='devicerole', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='frontport', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='frontport', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='frontport', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='frontporttemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='frontporttemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='frontporttemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='interface', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='interface', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='interface', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='interfacetemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='interfacetemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='interfacetemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='inventoryitem', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='inventoryitem', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='inventoryitem', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='manufacturer', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='platform', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='poweroutlet', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='poweroutlet', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='poweroutlet', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='poweroutlettemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='poweroutlettemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='poweroutlettemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='powerport', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='powerport', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='powerport', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='powerporttemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='powerporttemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='powerporttemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='rackgroup', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='rackrole', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='rearport', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='rearport', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='rearport', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='rearporttemplate', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='rearporttemplate', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='rearporttemplate', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), - migrations.AddField( - model_name='region', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='cable', name='id', diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index 7b718936d..d250227b7 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -6,7 +6,7 @@ from dcim.choices import * from dcim.constants import * from extras.models import ObjectChange from extras.utils import extras_features -from netbox.models import PrimaryModel +from netbox.models import BigIDModel from utilities.fields import NaturalOrderingField from utilities.querysets import RestrictedQuerySet from utilities.ordering import naturalize_interface @@ -28,7 +28,7 @@ __all__ = ( ) -class ComponentTemplateModel(PrimaryModel): +class ComponentTemplateModel(BigIDModel): device_type = models.ForeignKey( to='dcim.DeviceType', on_delete=models.CASCADE, diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py index f78363ba9..01d2712a7 100644 --- a/netbox/dcim/models/device_components.py +++ b/netbox/dcim/models/device_components.py @@ -13,7 +13,7 @@ from dcim.constants import * from dcim.fields import MACAddressField from extras.models import ObjectChange, TaggedItem from extras.utils import extras_features -from netbox.models import PrimaryModel +from netbox.models import BigIDModel from utilities.fields import NaturalOrderingField from utilities.mptt import TreeManager from utilities.ordering import naturalize_interface @@ -38,7 +38,7 @@ __all__ = ( ) -class ComponentModel(PrimaryModel): +class ComponentModel(BigIDModel): """ An abstract model inherited by any model which has a parent Device. """ diff --git a/netbox/extras/migrations/0054_standardize_models.py b/netbox/extras/migrations/0054_standardize_models.py index a836f365f..b6c95e77d 100644 --- a/netbox/extras/migrations/0054_standardize_models.py +++ b/netbox/extras/migrations/0054_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,11 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='configcontext', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='configcontext', name='id', diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py index d60a2cc96..bf0dfc873 100644 --- a/netbox/extras/models/models.py +++ b/netbox/extras/models/models.py @@ -16,7 +16,7 @@ from extras.choices import * from extras.constants import * from extras.querysets import ConfigContextQuerySet from extras.utils import extras_features, FeatureQuery, image_upload -from netbox.models import BigIDModel, PrimaryModel +from netbox.models import BigIDModel, ChangeLoggingMixin from utilities.querysets import RestrictedQuerySet from utilities.utils import deepmerge, render_jinja2 @@ -361,7 +361,7 @@ class ImageAttachment(BigIDModel): # Config contexts # -class ConfigContext(PrimaryModel): +class ConfigContext(ChangeLoggingMixin, BigIDModel): """ A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B diff --git a/netbox/extras/models/tags.py b/netbox/extras/models/tags.py index 22e9815a9..3a5b539b1 100644 --- a/netbox/extras/models/tags.py +++ b/netbox/extras/models/tags.py @@ -2,7 +2,7 @@ from django.db import models from django.utils.text import slugify from taggit.models import TagBase, GenericTaggedItemBase -from netbox.models import BigIDModel, CoreModel +from netbox.models import BigIDModel, ChangeLoggingMixin from utilities.choices import ColorChoices from utilities.fields import ColorField from utilities.querysets import RestrictedQuerySet @@ -12,7 +12,7 @@ from utilities.querysets import RestrictedQuerySet # Tags # -class Tag(TagBase, CoreModel): +class Tag(ChangeLoggingMixin, BigIDModel, TagBase): color = ColorField( default=ColorChoices.COLOR_GREY ) diff --git a/netbox/ipam/migrations/0044_standardize_models.py b/netbox/ipam/migrations/0044_standardize_models.py index 2762c9973..a4ad77053 100644 --- a/netbox/ipam/migrations/0044_standardize_models.py +++ b/netbox/ipam/migrations/0044_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,21 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='rir', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='role', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='vlangroup', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='aggregate', name='id', diff --git a/netbox/netbox/models.py b/netbox/netbox/models.py index c0b0ce7ae..ad11dd18f 100644 --- a/netbox/netbox/models.py +++ b/netbox/netbox/models.py @@ -16,23 +16,13 @@ __all__ = ( ) -class BigIDModel(models.Model): - """ - Abstract base model for all Schematic data objects. Ensures the use of a 64-bit PK. - """ - id = models.BigAutoField( - primary_key=True - ) +# +# Mixins +# - class Meta: - abstract = True - - -class CoreModel(BigIDModel): +class ChangeLoggingMixin(models.Model): """ - Base class for all core objects. Provides the following: - - Change logging - - Custom field support + Provides change logging support. """ created = models.DateField( auto_now_add=True, @@ -62,9 +52,9 @@ class CoreModel(BigIDModel): ) -class PrimaryModel(CoreModel): +class CustomFieldsMixin(models.Model): """ - Primary models represent real objects within the infrastructure being modeled. + Provides support for custom fields. """ custom_field_data = models.JSONField( encoder=DjangoJSONEncoder, @@ -114,7 +104,33 @@ class PrimaryModel(CoreModel): raise ValidationError(f"Missing required custom field '{cf.name}'.") -class NestedGroupModel(PrimaryModel, MPTTModel): +# +# Base model classes + +class BigIDModel(models.Model): + """ + Abstract base model for all data objects. Ensures the use of a 64-bit PK. + """ + id = models.BigAutoField( + primary_key=True + ) + + class Meta: + abstract = True + + +class PrimaryModel(ChangeLoggingMixin, CustomFieldsMixin, BigIDModel): + """ + Primary models represent real objects within the infrastructure being modeled. + """ + # TODO + # tags = TaggableManager(through=TaggedItem) + + class Meta: + abstract = True + + +class NestedGroupModel(ChangeLoggingMixin, BigIDModel, MPTTModel): """ Base model for objects which are used to form a hierarchy (regions, locations, etc.). These models nest recursively using MPTT. Within each parent, each child instance must have a unique name. @@ -157,7 +173,7 @@ class NestedGroupModel(PrimaryModel, MPTTModel): ) -class OrganizationalModel(PrimaryModel): +class OrganizationalModel(ChangeLoggingMixin, BigIDModel): """ Organizational models are those which are used solely to categorize and qualify other objects, and do not convey any real information about the infrastructure being modeled (for example, functional device roles). Organizational diff --git a/netbox/secrets/migrations/0013_standardize_models.py b/netbox/secrets/migrations/0013_standardize_models.py index 9de8dec95..ad18536dc 100644 --- a/netbox/secrets/migrations/0013_standardize_models.py +++ b/netbox/secrets/migrations/0013_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,11 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='secretrole', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='secret', name='id', diff --git a/netbox/tenancy/migrations/0012_standardize_models.py b/netbox/tenancy/migrations/0012_standardize_models.py index 7ce55cf42..6a277fa7c 100644 --- a/netbox/tenancy/migrations/0012_standardize_models.py +++ b/netbox/tenancy/migrations/0012_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,11 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='tenantgroup', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), migrations.AlterField( model_name='tenant', name='id', diff --git a/netbox/users/migrations/0011_standardize_models.py b/netbox/users/migrations/0011_standardize_models.py index abfbd8702..3c514dd2a 100644 --- a/netbox/users/migrations/0011_standardize_models.py +++ b/netbox/users/migrations/0011_standardize_models.py @@ -1,3 +1,5 @@ +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -18,9 +20,4 @@ class Migration(migrations.Migration): name='id', field=models.BigAutoField(primary_key=True, serialize=False), ), - migrations.AlterField( - model_name='userconfig', - name='id', - field=models.BigAutoField(primary_key=True, serialize=False), - ), ] diff --git a/netbox/users/models.py b/netbox/users/models.py index 529732e65..00e18148c 100644 --- a/netbox/users/models.py +++ b/netbox/users/models.py @@ -51,7 +51,7 @@ class AdminUser(User): # User preferences # -class UserConfig(BigIDModel): +class UserConfig(models.Model): """ This model stores arbitrary user-specific preferences in a JSON data structure. """ diff --git a/netbox/virtualization/migrations/0020_standardize_models.py b/netbox/virtualization/migrations/0020_standardize_models.py index 15585100d..932403698 100644 --- a/netbox/virtualization/migrations/0020_standardize_models.py +++ b/netbox/virtualization/migrations/0020_standardize_models.py @@ -1,4 +1,5 @@ -import django.core.serializers.json +# Generated by Django 3.2b1 on 2021-02-26 21:11 + from django.db import migrations, models @@ -9,31 +10,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AddField( - model_name='clustergroup', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='clustertype', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='vminterface', - name='created', - field=models.DateField(auto_now_add=True, null=True), - ), - migrations.AddField( - model_name='vminterface', - name='custom_field_data', - field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder), - ), - migrations.AddField( - model_name='vminterface', - name='last_updated', - field=models.DateTimeField(auto_now=True, null=True), - ), migrations.AlterField( model_name='cluster', name='id', diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index a6a63ab3b..364dde30b 100644 --- a/netbox/virtualization/models.py +++ b/netbox/virtualization/models.py @@ -9,7 +9,7 @@ from dcim.models import BaseInterface, Device from extras.models import ConfigContextModel, ObjectChange, TaggedItem from extras.querysets import ConfigContextModelQuerySet from extras.utils import extras_features -from netbox.models import OrganizationalModel, PrimaryModel +from netbox.models import BigIDModel, OrganizationalModel, PrimaryModel from utilities.fields import NaturalOrderingField from utilities.ordering import naturalize_interface from utilities.query_functions import CollateAsChar @@ -374,7 +374,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel): # @extras_features('export_templates', 'webhooks') -class VMInterface(PrimaryModel, BaseInterface): +class VMInterface(BigIDModel, BaseInterface): virtual_machine = models.ForeignKey( to='virtualization.VirtualMachine', on_delete=models.CASCADE,