mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Fixes #3868: Fix creation of interfaces for virtual machines
This commit is contained in:
@ -235,6 +235,10 @@ PATCH) to maintain backward compatibility. This behavior will be discontinued be
|
||||
* [#3706](https://github.com/digitalocean/netbox/issues/3706) - Increase `available_power` maximum value on PowerFeed
|
||||
* [#3731](https://github.com/digitalocean/netbox/issues/3731) - Change Graph.type to a ContentType foreign key field
|
||||
|
||||
## Bug Fixes (From Beta)
|
||||
|
||||
* [#3868](https://github.com/digitalocean/netbox/issues/3868) - Fix creation of interfaces for virtual machines
|
||||
|
||||
## API Changes
|
||||
|
||||
* Choice fields now use human-friendly strings for their values instead of integers (see
|
||||
|
@ -22,6 +22,7 @@ from utilities.fields import ColorField
|
||||
from utilities.managers import NaturalOrderingManager
|
||||
from utilities.models import ChangeLoggedModel
|
||||
from utilities.utils import foreground_color, serialize_object, to_meters
|
||||
from virtualization.choices import VMInterfaceTypeChoices
|
||||
|
||||
from .choices import *
|
||||
from .constants import *
|
||||
@ -2510,9 +2511,9 @@ class Interface(CableTermination, ComponentModel):
|
||||
raise ValidationError("An interface must belong to either a device or a virtual machine.")
|
||||
|
||||
# VM interfaces must be virtual
|
||||
if self.virtual_machine and self.type is not InterfaceTypeChoices.TYPE_VIRTUAL:
|
||||
if self.virtual_machine and self.type not in VMInterfaceTypeChoices.values():
|
||||
raise ValidationError({
|
||||
'type': "Virtual machines can only have virtual interfaces."
|
||||
'type': "Invalid interface type for a virtual machine: {}".format(self.type)
|
||||
})
|
||||
|
||||
# Virtual interfaces cannot be connected
|
||||
|
@ -16,6 +16,10 @@ class ChoiceSet(metaclass=ChoiceSetMeta):
|
||||
CHOICES = list()
|
||||
LEGACY_MAP = dict()
|
||||
|
||||
@classmethod
|
||||
def values(cls):
|
||||
return [c[0] for c in cls.CHOICES]
|
||||
|
||||
@classmethod
|
||||
def slug_to_id(cls, slug):
|
||||
"""
|
||||
|
@ -99,7 +99,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
|
||||
|
||||
class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
|
||||
virtual_machine = NestedVirtualMachineSerializer()
|
||||
type = ChoiceField(choices=InterfaceTypeChoices, default=InterfaceTypeChoices.TYPE_VIRTUAL, required=False)
|
||||
type = ChoiceField(choices=VMInterfaceTypeChoices, default=VMInterfaceTypeChoices.TYPE_VIRTUAL, required=False)
|
||||
mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_null=True)
|
||||
untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
|
||||
tagged_vlans = SerializedPKRelatedField(
|
||||
|
@ -1,3 +1,4 @@
|
||||
from dcim.choices import InterfaceTypeChoices
|
||||
from utilities.choices import ChoiceSet
|
||||
|
||||
|
||||
@ -22,3 +23,16 @@ class VirtualMachineStatusChoices(ChoiceSet):
|
||||
STATUS_ACTIVE: 1,
|
||||
STATUS_STAGED: 3,
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# Interface types (for VirtualMachines)
|
||||
#
|
||||
|
||||
class VMInterfaceTypeChoices(ChoiceSet):
|
||||
|
||||
TYPE_VIRTUAL = InterfaceTypeChoices.TYPE_VIRTUAL
|
||||
|
||||
CHOICES = (
|
||||
(TYPE_VIRTUAL, 'Virtual'),
|
||||
)
|
||||
|
@ -2,7 +2,7 @@ from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from taggit.forms import TagField
|
||||
|
||||
from dcim.choices import InterfaceModeChoices, InterfaceTypeChoices
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.forms import INTERFACE_MODE_HELP_TEXT
|
||||
from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
|
||||
from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
|
||||
@ -18,10 +18,6 @@ from utilities.forms import (
|
||||
from .choices import *
|
||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
|
||||
|
||||
VIFACE_TYPE_CHOICES = (
|
||||
(InterfaceTypeChoices.TYPE_VIRTUAL, 'Virtual'),
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Cluster types
|
||||
@ -740,8 +736,8 @@ class InterfaceCreateForm(ComponentForm):
|
||||
label='Name'
|
||||
)
|
||||
type = forms.ChoiceField(
|
||||
choices=VIFACE_TYPE_CHOICES,
|
||||
initial=InterfaceTypeChoices.TYPE_VIRTUAL,
|
||||
choices=VMInterfaceTypeChoices,
|
||||
initial=VMInterfaceTypeChoices.TYPE_VIRTUAL,
|
||||
widget=forms.HiddenInput()
|
||||
)
|
||||
enabled = forms.BooleanField(
|
||||
@ -925,8 +921,8 @@ class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
|
||||
|
||||
class VirtualMachineBulkAddInterfaceForm(VirtualMachineBulkAddComponentForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=VIFACE_TYPE_CHOICES,
|
||||
initial=InterfaceTypeChoices.TYPE_VIRTUAL,
|
||||
choices=VMInterfaceTypeChoices,
|
||||
initial=VMInterfaceTypeChoices.TYPE_VIRTUAL,
|
||||
widget=forms.HiddenInput()
|
||||
)
|
||||
enabled = forms.BooleanField(
|
||||
|
Reference in New Issue
Block a user