From 74e65c02aa1e9a2d32bf454f4aac38353cdd10b0 Mon Sep 17 00:00:00 2001 From: Timotej Lazar Date: Mon, 10 Feb 2025 16:40:49 +0100 Subject: [PATCH] vlans: allow specifying native VLAN for tagged interfaces --- vlans.py | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/vlans.py b/vlans.py index 2736836..83077f5 100644 --- a/vlans.py +++ b/vlans.py @@ -103,7 +103,7 @@ class SetVLANScript(Script): description = 'Set tagged and untagged VLANs on access switch ports' fieldsets = ( ('Ports', ('access_ports', 'switch', 'switch_ports')), - ('Settings', ('vlans', 'enable')) + ('Settings', ('untagged_vlan', 'tagged_vlans', 'enable')) ) scheduling_enabled = False @@ -113,14 +113,21 @@ class SetVLANScript(Script): description='Limit selection to this switch') switch_ports = MultiObjectVar(model=Interface, query_params={'device_id': '$switch'}, required=False, description='Select switch ports directly') - vlans = MultiObjectVar(model=VLAN, label='VLANs', required=False, - description='Select multiple VLANs to put selected ports into tagged mode') + untagged_vlan = ObjectVar(model=VLAN, label='Untagged VLAN', required=False, + description='Untagged (native) VLAN for selected ports') + tagged_vlans = MultiObjectVar(model=VLAN, label='Tagged VLANs', required=False, + description='Tagged VLANs for selected port') enable = BooleanVar(label='Enable ports', default=True) def run(self, data, commit): all_ports = list(data['switch_ports']) + untagged_vlan = data['untagged_vlan'] + tagged_vlans = list(data['tagged_vlans']) modified_switches = set() + if not untagged_vlan and not tagged_vlans: + raise AbortScript('at least one VLAN must be specified') + # Trace doesn’t work rear ports for some reason, so do it manually. # Assumes this layout (f=front port, r=rear port, i=interface, ---=cable): # 1f:012.23:r1 --- 23r:panel-012:f23 --- 46i:sw-xyzzy @@ -132,27 +139,19 @@ class SetVLANScript(Script): for port in all_ports: port.enabled = data['enable'] - match len(data['vlans']): - case 0: - port.mode = 'access' - port.save() - port.tagged_vlans.clear() - port.untagged_vlan = None - case 1: - port.mode = 'access' - port.save() - port.tagged_vlans.clear() - port.untagged_vlan = data['vlans'][0] - case _: - port.mode = 'tagged' - port.save() - port.tagged_vlans.set(data['vlans']) - port.untagged_vlan = None + if tagged_vlans: + self.log_info(f'{port.device.name} {port} is tagged') + port.mode = 'tagged' + port.save() + port.tagged_vlans.set(tagged_vlans) + else: + self.log_info(f'{port.device.name} {port} is access') + port.mode = 'access' + port.save() + port.untagged_vlan = untagged_vlan port.full_clean() port.save() modified_switches.add(port.device.name) - - self.log_info(f'{port.device.name} {port} is {port.mode} for {",".join(str(vlan.vid) for vlan in data["vlans"])}') + self.log_info(f'{port.device.name} {port} is {port.mode} with untagged_vlan: {port.untagged_vlan} tagged_vlans: {[v.vid for v in port.tagged_vlans.all()]}') self.log_success(f'modified switches {",".join(sorted(modified_switches))}') -