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()
 | 
			
		||||
    manufacturer = forms.ModelChoiceField(
 | 
			
		||||
        queryset=Manufacturer.objects.all(),
 | 
			
		||||
        required=True,
 | 
			
		||||
        required=False,
 | 
			
		||||
        to_field_name='name',
 | 
			
		||||
        help_text='Manufacturer name',
 | 
			
		||||
        error_messages={
 | 
			
		||||
 
 | 
			
		||||
@@ -43,13 +43,13 @@ class InterfaceQuerySet(QuerySet):
 | 
			
		||||
        }[method]
 | 
			
		||||
 | 
			
		||||
        TYPE_RE = r"SUBSTRING({} FROM '^([^0-9]+)')"
 | 
			
		||||
        ID_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)([0-9]+)$') AS integer)"
 | 
			
		||||
        SLOT_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?([0-9]+)\/') AS integer)"
 | 
			
		||||
        SUBSLOT_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/)([0-9]+)') AS integer), 0)"
 | 
			
		||||
        POSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/){{2}}([0-9]+)') AS integer), 0)"
 | 
			
		||||
        SUBPOSITION_RE = r"COALESCE(CAST(SUBSTRING({} FROM '^(?:[^0-9]+)?(?:[0-9]+\/){{3}}([0-9]+)') AS integer), 0)"
 | 
			
		||||
        CHANNEL_RE = r"COALESCE(CAST(SUBSTRING({} FROM ':([0-9]+)(\.[0-9]+)?$') AS integer), 0)"
 | 
			
		||||
        VC_RE = r"COALESCE(CAST(SUBSTRING({} FROM '\.([0-9]+)$') AS integer), 0)"
 | 
			
		||||
        ID_RE = r"CAST(SUBSTRING({} FROM '^(?:[^0-9]+)(\d{{1,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]+)?(?:\d{{1,9}}\/)(\d{{1,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]+)?(?:\d{{1,9}}\/){{3}}(\d{{1,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 '\.(\d{{1,9}})$') AS integer), 0)"
 | 
			
		||||
 | 
			
		||||
        fields = {
 | 
			
		||||
            '_type': RawSQL(TYPE_RE.format(sql_col), []),
 | 
			
		||||
 
 | 
			
		||||
@@ -508,7 +508,7 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
 | 
			
		||||
 | 
			
		||||
        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']:
 | 
			
		||||
            parent = self.cleaned_data['interface'].parent
 | 
			
		||||
            if ipaddress.address.version == 4:
 | 
			
		||||
@@ -516,14 +516,12 @@ class IPAddressForm(BootstrapMixin, TenancyForm, ReturnURLForm, CustomFieldForm)
 | 
			
		||||
            else:
 | 
			
		||||
                parent.primary_ip6 = ipaddress
 | 
			
		||||
            parent.save()
 | 
			
		||||
 | 
			
		||||
        # Clear assignment as primary for device if set.
 | 
			
		||||
        elif self.cleaned_data['interface']:
 | 
			
		||||
            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.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.save()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ if sys.version_info[0] < 3:
 | 
			
		||||
        DeprecationWarning
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
VERSION = '2.3.3-dev'
 | 
			
		||||
VERSION = '2.4-dev'
 | 
			
		||||
 | 
			
		||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -205,7 +205,8 @@ class ArrayFieldSelectMultiple(SelectWithDisabled, forms.SelectMultiple):
 | 
			
		||||
 | 
			
		||||
    def optgroups(self, name, value, attrs=None):
 | 
			
		||||
        # Split the delimited string of values into a list
 | 
			
		||||
        value = value[0].split(self.delimiter)
 | 
			
		||||
        if value:
 | 
			
		||||
            value = value[0].split(self.delimiter)
 | 
			
		||||
        return super(ArrayFieldSelectMultiple, self).optgroups(name, value, attrs)
 | 
			
		||||
 | 
			
		||||
    def value_from_datadict(self, data, files, name):
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ def csv_format(data):
 | 
			
		||||
    for value in data:
 | 
			
		||||
 | 
			
		||||
        # Represent None or False with empty string
 | 
			
		||||
        if value in [None, False]:
 | 
			
		||||
        if value is None or value is False:
 | 
			
		||||
            csv.append('')
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,10 +3,10 @@ from __future__ import unicode_literals
 | 
			
		||||
from rest_framework import serializers
 | 
			
		||||
 | 
			
		||||
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 extras.api.customfields import CustomFieldModelSerializer
 | 
			
		||||
from ipam.models import IPAddress
 | 
			
		||||
from ipam.models import IPAddress, VLAN
 | 
			
		||||
from tenancy.api.serializers import NestedTenantSerializer
 | 
			
		||||
from utilities.api import ChoiceFieldSerializer, ValidatedModelSerializer, WritableNestedSerializer
 | 
			
		||||
from virtualization.constants import VM_STATUS_CHOICES
 | 
			
		||||
@@ -116,14 +116,26 @@ class NestedVirtualMachineSerializer(WritableNestedSerializer):
 | 
			
		||||
# 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()
 | 
			
		||||
    form_factor = serializers.IntegerField(default=IFACE_FF_VIRTUAL)
 | 
			
		||||
    mode = ChoiceFieldSerializer(choices=IFACE_MODE_CHOICES)
 | 
			
		||||
    untagged_vlan = InterfaceVLANSerializer()
 | 
			
		||||
    tagged_vlans = InterfaceVLANSerializer(many=True)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Interface
 | 
			
		||||
        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