1
0
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:
Jeremy Stretch
2020-01-09 14:53:18 -05:00
parent 40fe6666e3
commit fe490d144a
6 changed files with 31 additions and 12 deletions

View File

@ -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 * [#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 * [#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 ## API Changes
* Choice fields now use human-friendly strings for their values instead of integers (see * Choice fields now use human-friendly strings for their values instead of integers (see

View File

@ -22,6 +22,7 @@ from utilities.fields import ColorField
from utilities.managers import NaturalOrderingManager from utilities.managers import NaturalOrderingManager
from utilities.models import ChangeLoggedModel from utilities.models import ChangeLoggedModel
from utilities.utils import foreground_color, serialize_object, to_meters from utilities.utils import foreground_color, serialize_object, to_meters
from virtualization.choices import VMInterfaceTypeChoices
from .choices import * from .choices import *
from .constants 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.") raise ValidationError("An interface must belong to either a device or a virtual machine.")
# VM interfaces must be virtual # 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({ 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 # Virtual interfaces cannot be connected

View File

@ -16,6 +16,10 @@ class ChoiceSet(metaclass=ChoiceSetMeta):
CHOICES = list() CHOICES = list()
LEGACY_MAP = dict() LEGACY_MAP = dict()
@classmethod
def values(cls):
return [c[0] for c in cls.CHOICES]
@classmethod @classmethod
def slug_to_id(cls, slug): def slug_to_id(cls, slug):
""" """

View File

@ -99,7 +99,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer): class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
virtual_machine = NestedVirtualMachineSerializer() 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) mode = ChoiceField(choices=InterfaceModeChoices, required=False, allow_null=True)
untagged_vlan = NestedVLANSerializer(required=False, allow_null=True) untagged_vlan = NestedVLANSerializer(required=False, allow_null=True)
tagged_vlans = SerializedPKRelatedField( tagged_vlans = SerializedPKRelatedField(

View File

@ -1,3 +1,4 @@
from dcim.choices import InterfaceTypeChoices
from utilities.choices import ChoiceSet from utilities.choices import ChoiceSet
@ -22,3 +23,16 @@ class VirtualMachineStatusChoices(ChoiceSet):
STATUS_ACTIVE: 1, STATUS_ACTIVE: 1,
STATUS_STAGED: 3, STATUS_STAGED: 3,
} }
#
# Interface types (for VirtualMachines)
#
class VMInterfaceTypeChoices(ChoiceSet):
TYPE_VIRTUAL = InterfaceTypeChoices.TYPE_VIRTUAL
CHOICES = (
(TYPE_VIRTUAL, 'Virtual'),
)

View File

@ -2,7 +2,7 @@ from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from taggit.forms import TagField 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.forms import INTERFACE_MODE_HELP_TEXT
from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site from dcim.models import Device, DeviceRole, Interface, Platform, Rack, Region, Site
from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm from extras.forms import AddRemoveTagsForm, CustomFieldBulkEditForm, CustomFieldForm, CustomFieldFilterForm
@ -18,10 +18,6 @@ from utilities.forms import (
from .choices import * from .choices import *
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine
VIFACE_TYPE_CHOICES = (
(InterfaceTypeChoices.TYPE_VIRTUAL, 'Virtual'),
)
# #
# Cluster types # Cluster types
@ -740,8 +736,8 @@ class InterfaceCreateForm(ComponentForm):
label='Name' label='Name'
) )
type = forms.ChoiceField( type = forms.ChoiceField(
choices=VIFACE_TYPE_CHOICES, choices=VMInterfaceTypeChoices,
initial=InterfaceTypeChoices.TYPE_VIRTUAL, initial=VMInterfaceTypeChoices.TYPE_VIRTUAL,
widget=forms.HiddenInput() widget=forms.HiddenInput()
) )
enabled = forms.BooleanField( enabled = forms.BooleanField(
@ -925,8 +921,8 @@ class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
class VirtualMachineBulkAddInterfaceForm(VirtualMachineBulkAddComponentForm): class VirtualMachineBulkAddInterfaceForm(VirtualMachineBulkAddComponentForm):
type = forms.ChoiceField( type = forms.ChoiceField(
choices=VIFACE_TYPE_CHOICES, choices=VMInterfaceTypeChoices,
initial=InterfaceTypeChoices.TYPE_VIRTUAL, initial=VMInterfaceTypeChoices.TYPE_VIRTUAL,
widget=forms.HiddenInput() widget=forms.HiddenInput()
) )
enabled = forms.BooleanField( enabled = forms.BooleanField(