mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Merge branch 'develop' into develop-2.4
This commit is contained in:
@ -706,7 +706,7 @@ class PlatformCSVForm(forms.ModelForm):
|
|||||||
slug = SlugField()
|
slug = SlugField()
|
||||||
manufacturer = forms.ModelChoiceField(
|
manufacturer = forms.ModelChoiceField(
|
||||||
queryset=Manufacturer.objects.all(),
|
queryset=Manufacturer.objects.all(),
|
||||||
required=True,
|
required=False,
|
||||||
to_field_name='name',
|
to_field_name='name',
|
||||||
help_text='Manufacturer name',
|
help_text='Manufacturer name',
|
||||||
error_messages={
|
error_messages={
|
||||||
|
@ -43,13 +43,13 @@ class InterfaceQuerySet(QuerySet):
|
|||||||
}[method]
|
}[method]
|
||||||
|
|
||||||
TYPE_RE = r"SUBSTRING({} FROM '^([^0-9]+)')"
|
TYPE_RE = r"SUBSTRING({} FROM '^([^0-9]+)')"
|
||||||
ID_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)([0-9]+)$') AS integer)"
|
ID_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)(\d{{1,9}})$') AS integer)"
|
||||||
SLOT_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?([0-9]+)\/') AS integer)"
|
SLOT_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(\d{{1,9}})\/') AS integer)"
|
||||||
SUBSLOT_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/)([0-9]+)') AS integer), 0)"
|
SUBSLOT_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:\d{{1,9}}\/)(\d{{1,9}})') AS integer), 0)"
|
||||||
POSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/){{2}}([0-9]+)') AS integer), 0)"
|
POSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:\d{{1,9}}\/){{2}}(\d{{1,9}})') AS integer), 0)"
|
||||||
SUBPOSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/){{3}}([0-9]+)') AS integer), 0)"
|
SUBPOSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:\d{{1,9}}\/){{3}}(\d{{1,9}})') AS integer), 0)"
|
||||||
CHANNEL_RE = r"COALESCE(CAST(SUBSTRING({} FROM ':([0-9]+)(\.[0-9]+)?$') AS integer), 0)"
|
CHANNEL_RE = r"COALESCE(CAST(SUBSTRING({} FROM ':(\d{{1,9}})(\.\d{{1,9}})?$') AS integer), 0)"
|
||||||
VC_RE = r"COALESCE(CAST(SUBSTRING({} FROM '\.([0-9]+)$') AS integer), 0)"
|
VC_RE = r"COALESCE(CAST(SUBSTRING({} FROM '\.(\d{{1,9}})$') AS integer), 0)"
|
||||||
|
|
||||||
fields = {
|
fields = {
|
||||||
'_type': RawSQL(TYPE_RE.format(sql_col), []),
|
'_type': RawSQL(TYPE_RE.format(sql_col), []),
|
||||||
|
@ -508,7 +508,7 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
|
|
||||||
ipaddress = super(IPAddressForm, self).save(*args, **kwargs)
|
ipaddress = super(IPAddressForm, self).save(*args, **kwargs)
|
||||||
|
|
||||||
# Assign this IPAddress as the primary for the associated Device.
|
# Assign/clear this IPAddress as the primary for the associated Device/VirtualMachine.
|
||||||
if self.cleaned_data['primary_for_parent']:
|
if self.cleaned_data['primary_for_parent']:
|
||||||
parent = self.cleaned_data['interface'].parent
|
parent = self.cleaned_data['interface'].parent
|
||||||
if ipaddress.address.version == 4:
|
if ipaddress.address.version == 4:
|
||||||
@ -516,14 +516,12 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
|
|||||||
else:
|
else:
|
||||||
parent.primary_ip6 = ipaddress
|
parent.primary_ip6 = ipaddress
|
||||||
parent.save()
|
parent.save()
|
||||||
|
|
||||||
# Clear assignment as primary for device if set.
|
|
||||||
elif self.cleaned_data['interface']:
|
elif self.cleaned_data['interface']:
|
||||||
parent = self.cleaned_data['interface'].parent
|
parent = self.cleaned_data['interface'].parent
|
||||||
if ipaddress.address.version == 4 and parent.primary_ip4 == self:
|
if ipaddress.address.version == 4 and parent.primary_ip4 == ipaddress:
|
||||||
parent.primary_ip4 = None
|
parent.primary_ip4 = None
|
||||||
parent.save()
|
parent.save()
|
||||||
elif ipaddress.address.version == 6 and parent.primary_ip6 == self:
|
elif ipaddress.address.version == 6 and parent.primary_ip6 == ipaddress:
|
||||||
parent.primary_ip6 = None
|
parent.primary_ip6 = None
|
||||||
parent.save()
|
parent.save()
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ if sys.version_info[0] < 3:
|
|||||||
DeprecationWarning
|
DeprecationWarning
|
||||||
)
|
)
|
||||||
|
|
||||||
VERSION = '2.3.3-dev'
|
VERSION = '2.4-dev'
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
@ -205,6 +205,7 @@ class ArrayFieldSelectMultiple(SelectWithDisabled, forms.SelectMultiple):
|
|||||||
|
|
||||||
def optgroups(self, name, value, attrs=None):
|
def optgroups(self, name, value, attrs=None):
|
||||||
# Split the delimited string of values into a list
|
# Split the delimited string of values into a list
|
||||||
|
if value:
|
||||||
value = value[0].split(self.delimiter)
|
value = value[0].split(self.delimiter)
|
||||||
return super(ArrayFieldSelectMultiple, self).optgroups(name, value, attrs)
|
return super(ArrayFieldSelectMultiple, self).optgroups(name, value, attrs)
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ def csv_format(data):
|
|||||||
for value in data:
|
for value in data:
|
||||||
|
|
||||||
# Represent None or False with empty string
|
# Represent None or False with empty string
|
||||||
if value in [None, False]:
|
if value is None or value is False:
|
||||||
csv.append('')
|
csv.append('')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ from __future__ import unicode_literals
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from dcim.api.serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
|
from dcim.api.serializers import NestedDeviceRoleSerializer, NestedPlatformSerializer, NestedSiteSerializer
|
||||||
from dcim.constants import IFACE_FF_VIRTUAL
|
from dcim.constants import IFACE_FF_VIRTUAL, IFACE_MODE_CHOICES
|
||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from extras.api.customfields import CustomFieldModelSerializer
|
from extras.api.customfields import CustomFieldModelSerializer
|
||||||
from ipam.models import IPAddress
|
from ipam.models import IPAddress, VLAN
|
||||||
from tenancy.api.serializers import NestedTenantSerializer
|
from tenancy.api.serializers import NestedTenantSerializer
|
||||||
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
|
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
|
||||||
from virtualization.constants import VM_STATUS_CHOICES
|
from virtualization.constants import VM_STATUS_CHOICES
|
||||||
@ -116,14 +116,26 @@ class NestedVirtualMachineSerializer(WritableNestedSerializer):
|
|||||||
# VM interfaces
|
# VM interfaces
|
||||||
#
|
#
|
||||||
|
|
||||||
class InterfaceSerializer(ValidatedModelSerializer):
|
# Cannot import ipam.api.serializers.NestedVLANSerializer due to circular dependency
|
||||||
|
class InterfaceVLANSerializer(serializers.ModelSerializer):
|
||||||
|
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = VLAN
|
||||||
|
fields = ['id', 'url', 'vid', 'name', 'display_name']
|
||||||
|
|
||||||
|
|
||||||
|
class InterfaceSerializer(serializers.ModelSerializer):
|
||||||
virtual_machine = NestedVirtualMachineSerializer()
|
virtual_machine = NestedVirtualMachineSerializer()
|
||||||
form_factor = serializers.IntegerField(default=IFACE_FF_VIRTUAL)
|
mode = ChoiceFieldSerializer(choices=IFACE_MODE_CHOICES)
|
||||||
|
untagged_vlan = InterfaceVLANSerializer()
|
||||||
|
tagged_vlans = InterfaceVLANSerializer(many=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Interface
|
model = Interface
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'name', 'virtual_machine', 'enabled', 'mac_address', 'mtu', 'description',
|
'id', 'name', 'virtual_machine', 'enabled', 'mac_address', 'mtu', 'mode', 'untagged_vlan', 'tagged_vlans',
|
||||||
|
'description',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user