diff --git a/netbox/templates/virtualization/vminterface.html b/netbox/templates/virtualization/vminterface.html index e3779ef21..e574e926e 100644 --- a/netbox/templates/virtualization/vminterface.html +++ b/netbox/templates/virtualization/vminterface.html @@ -57,9 +57,10 @@ - {% plugin_left_page object %} + {% plugin_left_page object %}
+ {% include 'inc/custom_fields_panel.html' %} {% include 'extras/inc/tags_panel.html' with tags=object.tags.all %} {% plugin_right_page object %}
diff --git a/netbox/templates/virtualization/vminterface_edit.html b/netbox/templates/virtualization/vminterface_edit.html index d4869aaf9..c0ad6e98c 100644 --- a/netbox/templates/virtualization/vminterface_edit.html +++ b/netbox/templates/virtualization/vminterface_edit.html @@ -31,6 +31,14 @@ {% render_field form.tagged_vlans %} + {% if form.custom_fields %} +
+
Custom Fields
+
+ {% render_custom_fields form %} +
+
+ {% endif %} {% endblock %} {% block buttons %} diff --git a/netbox/virtualization/api/serializers.py b/netbox/virtualization/api/serializers.py index e3b82e40a..f2640811b 100644 --- a/netbox/virtualization/api/serializers.py +++ b/netbox/virtualization/api/serializers.py @@ -103,7 +103,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer): # VM interfaces # -class VMInterfaceSerializer(TaggedObjectSerializer, ValidatedModelSerializer): +class VMInterfaceSerializer(TaggedObjectSerializer, CustomFieldModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:vminterface-detail') virtual_machine = NestedVirtualMachineSerializer() mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False) @@ -119,7 +119,7 @@ class VMInterfaceSerializer(TaggedObjectSerializer, ValidatedModelSerializer): model = VMInterface fields = [ 'id', 'url', 'virtual_machine', 'name', 'enabled', 'mtu', 'mac_address', 'description', 'mode', - 'untagged_vlan', 'tagged_vlans', 'tags', + 'untagged_vlan', 'tagged_vlans', 'tags', 'custom_fields', 'created', 'last_updated', ] def validate(self, data): diff --git a/netbox/virtualization/filters.py b/netbox/virtualization/filters.py index ea668c737..be9b70749 100644 --- a/netbox/virtualization/filters.py +++ b/netbox/virtualization/filters.py @@ -237,7 +237,7 @@ class VirtualMachineFilterSet( return queryset.exclude(params) -class VMInterfaceFilterSet(BaseFilterSet): +class VMInterfaceFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): q = django_filters.CharFilter( method='search', label='Search', diff --git a/netbox/virtualization/forms.py b/netbox/virtualization/forms.py index c2d0aee38..2aed5230f 100644 --- a/netbox/virtualization/forms.py +++ b/netbox/virtualization/forms.py @@ -576,7 +576,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil # VM interfaces # -class VMInterfaceForm(BootstrapMixin, InterfaceCommonForm, forms.ModelForm): +class VMInterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm): untagged_vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, diff --git a/netbox/virtualization/migrations/0020_standardize_models.py b/netbox/virtualization/migrations/0020_standardize_models.py index 42c44e83a..42dedbc72 100644 --- a/netbox/virtualization/migrations/0020_standardize_models.py +++ b/netbox/virtualization/migrations/0020_standardize_models.py @@ -54,4 +54,9 @@ class Migration(migrations.Migration): name='last_updated', field=models.DateTimeField(auto_now=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), + ), ] diff --git a/netbox/virtualization/models.py b/netbox/virtualization/models.py index 9744df3a5..4896e26bd 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, TaggedItem from extras.querysets import ConfigContextModelQuerySet from extras.utils import extras_features -from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel +from netbox.models import OrganizationalModel, PrimaryModel from utilities.fields import NaturalOrderingField from utilities.ordering import naturalize_interface from utilities.query_functions import CollateAsChar @@ -372,9 +372,8 @@ class VirtualMachine(PrimaryModel, ConfigContextModel): # Interfaces # -# TODO: Inherit from PrimaryModel -@extras_features('export_templates', 'webhooks') -class VMInterface(ChangeLoggedModel, BaseInterface): +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class VMInterface(PrimaryModel, BaseInterface): virtual_machine = models.ForeignKey( to='virtualization.VirtualMachine', on_delete=models.CASCADE,