From 62efb3e64413927fd9f58d4b8e4317304004f5e7 Mon Sep 17 00:00:00 2001
From: Bjarke Madsen <bjarke@nordu.net>
Date: Wed, 15 Jan 2025 11:15:51 +0100
Subject: [PATCH] add vlan_type support

---
 .../inventory_provider/interfaces.py          | 49 +++++++++++++++++--
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/brian_dashboard_manager/inventory_provider/interfaces.py b/brian_dashboard_manager/inventory_provider/interfaces.py
index 632b3dc..c342817 100644
--- a/brian_dashboard_manager/inventory_provider/interfaces.py
+++ b/brian_dashboard_manager/inventory_provider/interfaces.py
@@ -1,6 +1,7 @@
 import requests
 import logging
 import jsonschema
+from collections import defaultdict
 
 from requests.exceptions import HTTPError
 from enum import Enum, auto
@@ -54,6 +55,12 @@ class PORT_TYPES(Enum):
     UNKNOWN = auto()
 
 
+class VLAN_TYPES(Enum):
+    ACCESS = auto()
+    TRUNK = auto()
+    VLAN = auto()
+
+
 # only used in INTERFACE_LIST_SCHEMA and sphinx docs
 _DASHBOARD_IDS = [d.name for d in list(BRIAN_DASHBOARDS)]
 
@@ -61,6 +68,8 @@ _PORT_TYPES = [t.name for t in list(PORT_TYPES)]
 
 _INTERFACE_TYPES = [i.name for i in list(INTERFACE_TYPES)]
 
+_VLAN_TYPES = [i.name for i in list(VLAN_TYPES)]
+
 ROUTER_INTERFACES_SCHEMA = {
     "type": "array",
     "items": {
@@ -121,11 +130,12 @@ INTERFACE_LIST_SCHEMA = {
                     'type': 'array',
                     'items': {'$ref': '#/definitions/db_info'}
                 },
-                'port_type': {'enum': _PORT_TYPES}
+                'port_type': {'enum': _PORT_TYPES},
+                'vlan_type': {'enum': _VLAN_TYPES}
             },
             'required': [
                 'router', 'name', 'description',
-                'dashboards']
+                'dashboards', 'vlan_type']
         },
     },
 
@@ -337,7 +347,40 @@ def get_interfaces(host):
         interfaces = r.json()
     except HTTPError:
         logger.exception('Failed to get interfaces')
-        interfaces = []
+        return []
+
+    if 'vlan_type' not in interfaces[0]:
+        # inventory-provider changes are a bit slow, so do it on this side until it's released
+
+        ports_and_vlans = defaultdict(lambda: defaultdict(list))
+
+        for ifc in interfaces:
+            router = ifc['router']
+            name = ifc['name']
+
+            if '.' in name:
+                name = name.split('.')[0]
+
+            ports_and_vlans[router][name].append(ifc)
+
+        # Add interface_type to each interface
+        # It's used as a filter in the dashboard manager to determine which interfaces are trunks & has VLANs
+        for router, ifcs in ports_and_vlans.items():
+            for base_ifc, ifc_list in ifcs.items():
+
+                if len(ifc_list) == 1:
+                    ifc_list[0]['vlan_type'] = VLAN_TYPES.ACCESS.name
+                    continue
+
+                ifc_list.sort(key=lambda x: x['name'])
+                base = ifc_list.pop(0)
+                if base['name'] != base_ifc:
+                    base['vlan_type'] = VLAN_TYPES.VLAN.name
+                else:
+                    base['vlan_type'] = VLAN_TYPES.TRUNK.name
+
+                for ifc in ifc_list:
+                    ifc['vlan_type'] = VLAN_TYPES.VLAN.name
 
     jsonschema.validate(interfaces, INTERFACE_LIST_SCHEMA)
 
-- 
GitLab