Cannot add a tagged vlan to the interface via Custom Script. #10226

Closed
opened 2025-12-29 21:28:37 +01:00 by adam · 0 comments
Owner

Originally created by @LuaLua10 on GitHub (Sep 11, 2024).

Deployment Type

Self-hosted

NetBox Version

NetBox Community v4.1.0

Python Version

3.12

Steps to Reproduce

  1. Upload the script to the Netbox using any of the methods.
The code for adding VLANs to interfaces
    # Set VLANs and labels
    for interface in Interface.objects.filter(device=device):
        if interface.type != 'Virtual':
            if interface.label == 'User port':
                interface.mode = 'access'
                interface.untagged_vlan = data['access_vlan']
                self.log_success(f"Added access VLAN to {interface}: {data['access_vlan']}")
            if interface.label in ['Service', 'Up-Link']:
                # Set label
                if data['up_link_interface'].name == interface.name:
                    interface.label = 'Up-Link'
                    self.log_success(f"Set Up-Link label for interface {interface}")
                else:
                    interface.label = 'Service'
                    self.log_success(f"Set Service label for interface {interface}")
                # Set tagged VLANs (trunk)
                interface.mode = 'tagged'
                trunk_vlans = [data['access_vlan'].id]
                self.log_success(f"Added access VLAN (tagged) on {interface}: "
                                 f"{data['access_vlan']}")
                # Extra VLANs
                if len(data['extra_vlans']) != 0:
                    for vlan in data['extra_vlans']:
                        trunk_vlans.append(vlan.id)
                    self.log_success(f"Added extra VLANs (tagged) on {interface}: "
                                     f"{[vlan for vlan in data['extra_vlans']]}")
                # Default VLANs
                if data['default_vlans']:
                    default_vlans = VLAN.objects.filter(tags=13)
                    for vlan in default_vlans:
                        trunk_vlans.append(vlan.id)
                    self.log_success(f"Added default VLANs (tagged) on {interface}: "
                                     f"{[vlan for vlan in default_vlans]}")
                # Set all tagged VLANs
                interface.tagged_vlans.set(trunk_vlans)
                self.log_success(f"ALL VLANs (tagged) on {interface}: "
                                 f"{interface.tagged_vlans.all()}")
            interface.save()          
The full version of the script

from ipam.models import VRF, VLAN, IPAddress
from ipam.choices import IPAddressStatusChoices
from dcim.choices import DeviceStatusChoices, SiteStatusChoices
from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site, Location, Platform, Rack, Interface, InterfaceTemplate
from extras.models import Tag, ConfigTemplate
from extras.scripts import *


class NewDeviceScript(Script):

    class Meta:
        name = "Create new device"
        description = "Create a new device"

    device_name = StringVar(
        label="Device name",
        description="Name of the device"
    )
    asset_tag = StringVar(
        label="Device tag",
        description="ID of the device",
    )
    role = ObjectVar(
        label='Role',
        description="Role of the device",
        model=DeviceRole,
    )
    platform = ObjectVar(
        label='Platform',
        description="Platform of the device",
        model=Platform,
    )
    manufacturer = ObjectVar(
        label='Manufacturer',
        description="Manufacturer of the device",
        model=Manufacturer,
        required=False
    )
    device_type = ObjectVar(
        label='Device model',
        description="Model of the device",
        model=DeviceType,
        query_params={
            'manufacturer_id': '$manufacturer'
        }
    )
    up_link_interface = ObjectVar(
        label='Up-Link interface',
        model=InterfaceTemplate,
        description="Up-Link interface to aggregation level.",
        query_params={
            'device_type_id': '$device_type',
        }
    )
    mac_address = StringVar(
        label="MAC address",
        description="MAC address of the MGMT interface"
    )
    primary_ip4 = IPAddressWithMaskVar(
        label="IPv4 address",
        description="IPv4 address for the MGMT interface"
    )
    primary_ip6 = IPAddressWithMaskVar(
        label="IPv6 address",
        required=False,
        description="IPv6 address for the MGMT interface"
    )
    igmp_ip4 = IPAddressWithMaskVar(
        label="IPv4 address for IGMP Proxy",
        description="IPv4 address for the IGMP interface"
    )
    igmp_ip6 = IPAddressWithMaskVar(
        label="IPv6 address for IGMP Proxy",
        required=False,
        description="IPv6 address for the IGMP interface"
    )
    vrf = ObjectVar(
        label='MGMT VRF',
        model=VRF,
        description="Name of the VRF for the MGMT interface",
        default=VRF.objects.get(name='Management VRF')
    )
    site = ObjectVar(
        label='Site',
        model=Site,
        description="Name of the site"
    )
    location = ObjectVar(
        label='Location',
        model=Location,
        description="Name of the location",
        query_params={
            'site_id': '$site'
        }
    )
    rack = ObjectVar(
        label='Rack',
        model=Rack,
        description="Name of the rack",
        query_params={
            'location_id': '$location'
        }
    )
    scheme_version = StringVar(
        label="Version of the scheme",
        description="The version of the scheme for configuration generator",
        default="v5",
        required=False
    )
    sequence_ip_number = IntegerVar(
        label="Sequence IP number",
        description="Sequence IP number for DHCP configuration",
        required=False
    )
    access_vlan = ObjectVar(
        label='Access VLAN',
        model=VLAN,
        description="Name of the access VLAN",
    )
    extra_vlans = MultiObjectVar(
        label='Extra VLANs',
        model=VLAN,
        description="Name of extra VLANs. VLANs will add to Service and Up-Link interfaces",
        required=False
    )
    default_vlans = BooleanVar(
        label='Default VLANs',
        description="Add default VLANs to device's interface (VLANs with 'Default access VLAN' tag).",
        required=False,
        default=True
    )
    status = ChoiceVar(
        DeviceStatusChoices,
        default=DeviceStatusChoices.STATUS_ACTIVE
    )
    device_config_template = ObjectVar(
        model=ConfigTemplate,
        label="Config Template",
        description="Name of Config Template. Choose depending on the model and role of the device.",
        required=False
    )
    device_tags = MultiObjectVar(
        model=Tag,
        label="Device tags",
        description="Name of tags",
        required=False
    )
    comments = TextVar(
        label="Comments",
        required=False
    )

    def run(self, data, commit):

        # Create device
        device = Device(
            name=data["device_name"],
            asset_tag=data["asset_tag"],
            role=data["role"],
            platform=data["platform"],
            device_type=data["device_type"],
            site=data["site"],
            location=data["location"],
            rack=data["rack"],
            status=data["status"],
            comments=data["comments"],
            custom_field_data=dict(access_vlan=data["access_vlan"].id,
                                   scheme_version=data["scheme_version"],
                                   sequence_ip_number=data["sequence_ip_number"]),
            config_template=data["device_config_template"]
        )
        device.full_clean()
        device.save()
        device.tags.set(data["device_tags"])
        self.log_success(f"Created new switch: {device}")

        # Set MGMT MAC address
        mgmt_interface = Interface.objects.get(name='Vlanif1', device=device)
        mgmt_interface.mac_address = data['mac_address']
        mgmt_interface.save()
        self.log_success(f"Added MGMT MAC address to {mgmt_interface}: {data['mac_address']}")

        # Set IGMP MAC address
        igmp_interface = Interface.objects.get(name='Vlanif901', device=device)
        igmp_interface.mac_address = data['mac_address']
        igmp_interface.save()
        self.log_success(f"Added IGMP MAC address to {mgmt_interface}: {data['mac_address']}")

        # Set MGMT IPv4 address
        mgmt_ipv4 = IPAddress(
            address=data['primary_ip4'],
            status=IPAddressStatusChoices.STATUS_ACTIVE,
            description='Management interface',
            vrf=data['vrf'],
            assigned_object=mgmt_interface
        )
        mgmt_ipv4.save()
        self.log_success(f"Created MGMT IPv4 address to {mgmt_interface.name}: {data['primary_ip4']}")

        # Set MGMT IPv6 address
        if data['primary_ip6']:
            mgmt_ipv6 = IPAddress(
                address=data['primary_ip6'],
                status=IPAddressStatusChoices.STATUS_ACTIVE,
                description='Management interface',
                vrf=data['vrf'],
                assigned_object=mgmt_interface
            )
            mgmt_ipv6.save()
            self.log_success(f"Created MGMT IPv6 address to {mgmt_interface.name}: {data['primary_ip6']}")

        # Set IGMP IPv4 address
        igmp_ipv4 = IPAddress(
            address=data['igmp_ip4'],
            status=IPAddressStatusChoices.STATUS_ACTIVE,
            description='IGMP interface',
            #vrf=data['vrf'],
            assigned_object=igmp_interface
        )
        igmp_ipv4.save()
        self.log_success(f"Created IGMP IPv4 address to {igmp_interface.name}: {data['igmp_ip4']}")

        # Set IGMP IPv6 address
        if data['igmp_ip6']:
            igmp_ipv6 = IPAddress(
                address=data['igmp_ip6'],
                status=IPAddressStatusChoices.STATUS_ACTIVE,
                description='IGMP interface',
                #vrf=data['vrf'],
                assigned_object=igmp_interface
            )
            igmp_ipv6.save()
            self.log_success(f"Created IGMP IPv6 address to {igmp_interface.name}: {data['igmp_ip6']}")

        # Set primary IPv4 address
        device.primary_ip4 = mgmt_ipv4
        device.save()
        self.log_success(f"Setted primary IPv4 address for {device.name}: {data['primary_ip4']}")

        # Set primary IPv6 address
        if data['primary_ip6']:
            device.primary_ip6 = mgmt_ipv6
            device.save()
            self.log_success(f"Setted primary IPv6 address for {device.name}: {data['primary_ip6']}")

        # Set VLANs and labels
        for interface in Interface.objects.filter(device=device):
            if interface.type != 'Virtual':
                if interface.label == 'User port':
                    interface.mode = 'access'
                    interface.untagged_vlan = data['access_vlan']
                    self.log_success(f"Added access VLAN to {interface}: {data['access_vlan']}")
                if interface.label in ['Service', 'Up-Link']:
                    # Set label
                    if data['up_link_interface'].name == interface.name:
                        interface.label = 'Up-Link'
                        self.log_success(f"Set Up-Link label for interface {interface}")
                    else:
                        interface.label = 'Service'
                        self.log_success(f"Set Service label for interface {interface}")
                    # Set tagged VLANs (trunk)
                    interface.mode = 'tagged'
                    trunk_vlans = [data['access_vlan'].id]
                    self.log_success(f"Added access VLAN (tagged) on {interface}: "
                                     f"{data['access_vlan']}")
                    # Extra VLANs
                    if len(data['extra_vlans']) != 0:
                        for vlan in data['extra_vlans']:
                            trunk_vlans.append(vlan.id)
                        self.log_success(f"Added extra VLANs (tagged) on {interface}: "
                                         f"{[vlan for vlan in data['extra_vlans']]}")
                    # Default VLANs
                    if data['default_vlans']:
                        default_vlans = VLAN.objects.filter(tags=13)
                        for vlan in default_vlans:
                            trunk_vlans.append(vlan.id)
                        self.log_success(f"Added default VLANs (tagged) on {interface}: "
                                         f"{[vlan for vlan in default_vlans]}")
                    # Set all tagged VLANs
                    interface.tagged_vlans.set(trunk_vlans)
                    self.log_success(f"ALL VLANs (tagged) on {interface}: "
                                     f"{interface.tagged_vlans.all()}")
                interface.save()

....

  1. Run the script by filling in the required fields.

Expected Behavior

The presence of tagged vlans on the interface.

Снимок экрана от 2024-09-11 17-01-41

Observed Behavior

Absence of tagged vlans on the interface.

Снимок экрана от 2024-09-11 17-02-07

Снимок экрана от 2024-09-11 17-23-50

Note that non-tagged vlans are added correctly.

Снимок экрана от 2024-09-11 17-02-45

Originally created by @LuaLua10 on GitHub (Sep 11, 2024). ### Deployment Type Self-hosted ### NetBox Version NetBox Community v4.1.0 ### Python Version 3.12 ### Steps to Reproduce 1. Upload the script to the Netbox using any of the methods. <details> <summary>The code for adding VLANs to interfaces</summary> # Set VLANs and labels for interface in Interface.objects.filter(device=device): if interface.type != 'Virtual': if interface.label == 'User port': interface.mode = 'access' interface.untagged_vlan = data['access_vlan'] self.log_success(f"Added access VLAN to {interface}: {data['access_vlan']}") if interface.label in ['Service', 'Up-Link']: # Set label if data['up_link_interface'].name == interface.name: interface.label = 'Up-Link' self.log_success(f"Set Up-Link label for interface {interface}") else: interface.label = 'Service' self.log_success(f"Set Service label for interface {interface}") # Set tagged VLANs (trunk) interface.mode = 'tagged' trunk_vlans = [data['access_vlan'].id] self.log_success(f"Added access VLAN (tagged) on {interface}: " f"{data['access_vlan']}") # Extra VLANs if len(data['extra_vlans']) != 0: for vlan in data['extra_vlans']: trunk_vlans.append(vlan.id) self.log_success(f"Added extra VLANs (tagged) on {interface}: " f"{[vlan for vlan in data['extra_vlans']]}") # Default VLANs if data['default_vlans']: default_vlans = VLAN.objects.filter(tags=13) for vlan in default_vlans: trunk_vlans.append(vlan.id) self.log_success(f"Added default VLANs (tagged) on {interface}: " f"{[vlan for vlan in default_vlans]}") # Set all tagged VLANs interface.tagged_vlans.set(trunk_vlans) self.log_success(f"ALL VLANs (tagged) on {interface}: " f"{interface.tagged_vlans.all()}") interface.save() </details> <details> <summary>The full version of the script</summary> ``` from ipam.models import VRF, VLAN, IPAddress from ipam.choices import IPAddressStatusChoices from dcim.choices import DeviceStatusChoices, SiteStatusChoices from dcim.models import Device, DeviceRole, DeviceType, Manufacturer, Site, Location, Platform, Rack, Interface, InterfaceTemplate from extras.models import Tag, ConfigTemplate from extras.scripts import * class NewDeviceScript(Script): class Meta: name = "Create new device" description = "Create a new device" device_name = StringVar( label="Device name", description="Name of the device" ) asset_tag = StringVar( label="Device tag", description="ID of the device", ) role = ObjectVar( label='Role', description="Role of the device", model=DeviceRole, ) platform = ObjectVar( label='Platform', description="Platform of the device", model=Platform, ) manufacturer = ObjectVar( label='Manufacturer', description="Manufacturer of the device", model=Manufacturer, required=False ) device_type = ObjectVar( label='Device model', description="Model of the device", model=DeviceType, query_params={ 'manufacturer_id': '$manufacturer' } ) up_link_interface = ObjectVar( label='Up-Link interface', model=InterfaceTemplate, description="Up-Link interface to aggregation level.", query_params={ 'device_type_id': '$device_type', } ) mac_address = StringVar( label="MAC address", description="MAC address of the MGMT interface" ) primary_ip4 = IPAddressWithMaskVar( label="IPv4 address", description="IPv4 address for the MGMT interface" ) primary_ip6 = IPAddressWithMaskVar( label="IPv6 address", required=False, description="IPv6 address for the MGMT interface" ) igmp_ip4 = IPAddressWithMaskVar( label="IPv4 address for IGMP Proxy", description="IPv4 address for the IGMP interface" ) igmp_ip6 = IPAddressWithMaskVar( label="IPv6 address for IGMP Proxy", required=False, description="IPv6 address for the IGMP interface" ) vrf = ObjectVar( label='MGMT VRF', model=VRF, description="Name of the VRF for the MGMT interface", default=VRF.objects.get(name='Management VRF') ) site = ObjectVar( label='Site', model=Site, description="Name of the site" ) location = ObjectVar( label='Location', model=Location, description="Name of the location", query_params={ 'site_id': '$site' } ) rack = ObjectVar( label='Rack', model=Rack, description="Name of the rack", query_params={ 'location_id': '$location' } ) scheme_version = StringVar( label="Version of the scheme", description="The version of the scheme for configuration generator", default="v5", required=False ) sequence_ip_number = IntegerVar( label="Sequence IP number", description="Sequence IP number for DHCP configuration", required=False ) access_vlan = ObjectVar( label='Access VLAN', model=VLAN, description="Name of the access VLAN", ) extra_vlans = MultiObjectVar( label='Extra VLANs', model=VLAN, description="Name of extra VLANs. VLANs will add to Service and Up-Link interfaces", required=False ) default_vlans = BooleanVar( label='Default VLANs', description="Add default VLANs to device's interface (VLANs with 'Default access VLAN' tag).", required=False, default=True ) status = ChoiceVar( DeviceStatusChoices, default=DeviceStatusChoices.STATUS_ACTIVE ) device_config_template = ObjectVar( model=ConfigTemplate, label="Config Template", description="Name of Config Template. Choose depending on the model and role of the device.", required=False ) device_tags = MultiObjectVar( model=Tag, label="Device tags", description="Name of tags", required=False ) comments = TextVar( label="Comments", required=False ) def run(self, data, commit): # Create device device = Device( name=data["device_name"], asset_tag=data["asset_tag"], role=data["role"], platform=data["platform"], device_type=data["device_type"], site=data["site"], location=data["location"], rack=data["rack"], status=data["status"], comments=data["comments"], custom_field_data=dict(access_vlan=data["access_vlan"].id, scheme_version=data["scheme_version"], sequence_ip_number=data["sequence_ip_number"]), config_template=data["device_config_template"] ) device.full_clean() device.save() device.tags.set(data["device_tags"]) self.log_success(f"Created new switch: {device}") # Set MGMT MAC address mgmt_interface = Interface.objects.get(name='Vlanif1', device=device) mgmt_interface.mac_address = data['mac_address'] mgmt_interface.save() self.log_success(f"Added MGMT MAC address to {mgmt_interface}: {data['mac_address']}") # Set IGMP MAC address igmp_interface = Interface.objects.get(name='Vlanif901', device=device) igmp_interface.mac_address = data['mac_address'] igmp_interface.save() self.log_success(f"Added IGMP MAC address to {mgmt_interface}: {data['mac_address']}") # Set MGMT IPv4 address mgmt_ipv4 = IPAddress( address=data['primary_ip4'], status=IPAddressStatusChoices.STATUS_ACTIVE, description='Management interface', vrf=data['vrf'], assigned_object=mgmt_interface ) mgmt_ipv4.save() self.log_success(f"Created MGMT IPv4 address to {mgmt_interface.name}: {data['primary_ip4']}") # Set MGMT IPv6 address if data['primary_ip6']: mgmt_ipv6 = IPAddress( address=data['primary_ip6'], status=IPAddressStatusChoices.STATUS_ACTIVE, description='Management interface', vrf=data['vrf'], assigned_object=mgmt_interface ) mgmt_ipv6.save() self.log_success(f"Created MGMT IPv6 address to {mgmt_interface.name}: {data['primary_ip6']}") # Set IGMP IPv4 address igmp_ipv4 = IPAddress( address=data['igmp_ip4'], status=IPAddressStatusChoices.STATUS_ACTIVE, description='IGMP interface', #vrf=data['vrf'], assigned_object=igmp_interface ) igmp_ipv4.save() self.log_success(f"Created IGMP IPv4 address to {igmp_interface.name}: {data['igmp_ip4']}") # Set IGMP IPv6 address if data['igmp_ip6']: igmp_ipv6 = IPAddress( address=data['igmp_ip6'], status=IPAddressStatusChoices.STATUS_ACTIVE, description='IGMP interface', #vrf=data['vrf'], assigned_object=igmp_interface ) igmp_ipv6.save() self.log_success(f"Created IGMP IPv6 address to {igmp_interface.name}: {data['igmp_ip6']}") # Set primary IPv4 address device.primary_ip4 = mgmt_ipv4 device.save() self.log_success(f"Setted primary IPv4 address for {device.name}: {data['primary_ip4']}") # Set primary IPv6 address if data['primary_ip6']: device.primary_ip6 = mgmt_ipv6 device.save() self.log_success(f"Setted primary IPv6 address for {device.name}: {data['primary_ip6']}") # Set VLANs and labels for interface in Interface.objects.filter(device=device): if interface.type != 'Virtual': if interface.label == 'User port': interface.mode = 'access' interface.untagged_vlan = data['access_vlan'] self.log_success(f"Added access VLAN to {interface}: {data['access_vlan']}") if interface.label in ['Service', 'Up-Link']: # Set label if data['up_link_interface'].name == interface.name: interface.label = 'Up-Link' self.log_success(f"Set Up-Link label for interface {interface}") else: interface.label = 'Service' self.log_success(f"Set Service label for interface {interface}") # Set tagged VLANs (trunk) interface.mode = 'tagged' trunk_vlans = [data['access_vlan'].id] self.log_success(f"Added access VLAN (tagged) on {interface}: " f"{data['access_vlan']}") # Extra VLANs if len(data['extra_vlans']) != 0: for vlan in data['extra_vlans']: trunk_vlans.append(vlan.id) self.log_success(f"Added extra VLANs (tagged) on {interface}: " f"{[vlan for vlan in data['extra_vlans']]}") # Default VLANs if data['default_vlans']: default_vlans = VLAN.objects.filter(tags=13) for vlan in default_vlans: trunk_vlans.append(vlan.id) self.log_success(f"Added default VLANs (tagged) on {interface}: " f"{[vlan for vlan in default_vlans]}") # Set all tagged VLANs interface.tagged_vlans.set(trunk_vlans) self.log_success(f"ALL VLANs (tagged) on {interface}: " f"{interface.tagged_vlans.all()}") interface.save() .... ``` </details> 2. Run the script by filling in the required fields. ### Expected Behavior The presence of tagged vlans on the interface. ![Снимок экрана от 2024-09-11 17-01-41](https://github.com/user-attachments/assets/f2970111-f607-40fa-ad73-4218b6d21195) ### Observed Behavior Absence of tagged vlans on the interface. ![Снимок экрана от 2024-09-11 17-02-07](https://github.com/user-attachments/assets/e31131d1-17cd-4ff0-809b-ec48fd87264b) ![Снимок экрана от 2024-09-11 17-23-50](https://github.com/user-attachments/assets/8f099b2f-b605-4e28-8620-10ed8650fed6) Note that non-tagged vlans are added correctly. ![Снимок экрана от 2024-09-11 17-02-45](https://github.com/user-attachments/assets/8059dc85-ae3e-4350-876e-6bd33164c7a3)
adam closed this issue 2025-12-29 21:28:37 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#10226