From dbd2732cf0d1efc1530b9b070e252d19c2b1d8f9 Mon Sep 17 00:00:00 2001 From: Maryam Mokhtarifar <maryam.mokhtarifar@geant.org> Date: Tue, 21 Jan 2025 16:56:39 +0100 Subject: [PATCH 1/6] Implement get_router_dashboard_data and _provision_vlan_dashboards --- brian_dashboard_manager/grafana/provision.py | 21 ++++++++++++-- brian_dashboard_manager/templating/helpers.py | 29 +++++++++++++++++-- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/brian_dashboard_manager/grafana/provision.py b/brian_dashboard_manager/grafana/provision.py index cacf06e..6cfafec 100644 --- a/brian_dashboard_manager/grafana/provision.py +++ b/brian_dashboard_manager/grafana/provision.py @@ -33,7 +33,7 @@ from brian_dashboard_manager.templating.helpers import \ get_nren_interface_data, get_dashboard_data, \ get_nren_dashboard_data, get_aggregate_interface_data, \ get_nren_interface_data_old, get_re_peer_dashboard_data, get_re_peer_interface_data, get_service_data, \ - get_service_dashboard_data, get_aggregate_service_data + get_service_dashboard_data, get_aggregate_service_data, get_router_dashboard_data, get_dashboard_data_dropdown from brian_dashboard_manager.templating.gws import generate_gws, generate_indirect from brian_dashboard_manager.templating.eumetsat import generate_eumetsat_multicast @@ -501,8 +501,25 @@ def _provision_vlan_dashboards(thread_executor: ThreadPoolExecutor, config, org_ folder_name = "VLAN Interfaces" # hardcoded, keep this in sync with the folder name specified in folders_to_keep logger.info(f'Provisioning {org_config["name"]}/{folder_name} dashboards') + excluded_folders = org_config.get('excluded_folders', {}) + if is_excluded_folder(excluded_folders, folder_name): + delete_folder(token, title=folder_name) + else: + folder = find_folder(token, title=folder_name) + if not folder: + raise Exception(f'Folder {folder_name} not found') + + folder_dashboards_by_name = list_folder_dashboards(token, folder['uid']) - yield + vlan_data = get_router_dashboard_data(interfaces) + provisioned = [] + for dashboard in get_dashboard_data_dropdown(vlan_data, ds_name, 'vlandash'): + rendered = render_simple_dashboard(**dashboard) + provisioned.append( + thread_executor.submit(create_dashboard, token, rendered, folder['id'], folder_dashboards_by_name) + ) + + yield from provisioned def _provision_gws_indirect(thread_executor: ThreadPoolExecutor, config, org_config, ds_name, token): diff --git a/brian_dashboard_manager/templating/helpers.py b/brian_dashboard_manager/templating/helpers.py index 6b2300c..8156dc5 100644 --- a/brian_dashboard_manager/templating/helpers.py +++ b/brian_dashboard_manager/templating/helpers.py @@ -11,6 +11,8 @@ from itertools import product from functools import partial, reduce from string import ascii_uppercase +from docutils.nodes import description + from brian_dashboard_manager.templating.render import create_panel, \ create_panel_target, create_dropdown_panel @@ -543,9 +545,31 @@ def get_router_dashboard_data(interfaces): :return: dictionary of routers (dashboards) and their interface data. """ - # TODO: implement + result = {} + + filtered_interfaces = [interface for interface in interfaces if interface.get('vlan_type') in {'TRUNK', 'VLAN'}] + + sorted_interfaces = sorted(filtered_interfaces, key=lambda x: x['name']) - return {} + for interface in sorted_interfaces: + description = interface['description'].strip() + interface_name = interface['name'] + host = interface['router'] + + router = host.replace('.geant.net', '') + panel_title = f'{router} - {{}} - {interface_name} - {description}' + + dashboard_name = interface['router'] + + dashboard = result.get(dashboard_name, []) + dashboard.append({ + 'title': panel_title, + 'interface': interface_name, # TODO NAME or interface data? + 'hostname': host + }) + result[dashboard_name] = dashboard + + return result def get_interface_data(interfaces): @@ -1130,7 +1154,6 @@ def get_dashboard_data_dropdown( def get_nren_dashboard_data(data, datasource, tag): - func = partial( get_dashboard_with_agg_data_single, datasource=datasource, -- GitLab From e08fa06526991316846e5c967c94953619d21108 Mon Sep 17 00:00:00 2001 From: Bjarke Madsen <bjarke@nordu.net> Date: Wed, 22 Jan 2025 10:19:57 +0100 Subject: [PATCH 2/6] Group by base interface --- brian_dashboard_manager/templating/helpers.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/brian_dashboard_manager/templating/helpers.py b/brian_dashboard_manager/templating/helpers.py index 8156dc5..e3f58ac 100644 --- a/brian_dashboard_manager/templating/helpers.py +++ b/brian_dashboard_manager/templating/helpers.py @@ -11,8 +11,6 @@ from itertools import product from functools import partial, reduce from string import ascii_uppercase -from docutils.nodes import description - from brian_dashboard_manager.templating.render import create_panel, \ create_panel_target, create_dropdown_panel @@ -560,14 +558,16 @@ def get_router_dashboard_data(interfaces): panel_title = f'{router} - {{}} - {interface_name} - {description}' dashboard_name = interface['router'] + dashboard = result.setdefault(dashboard_name, {}) + + base_interface = interface_name.split('.')[0] + dropdown = dashboard.setdefault(base_interface, []) - dashboard = result.get(dashboard_name, []) - dashboard.append({ + dropdown.append({ 'title': panel_title, - 'interface': interface_name, # TODO NAME or interface data? + 'interface': interface_name, 'hostname': host }) - result[dashboard_name] = dashboard return result -- GitLab From a2b3dc6dff9a68b363e8ca785e6b89e3b6c8ced3 Mon Sep 17 00:00:00 2001 From: Maryam Mokhtarifar <maryam.mokhtarifar@geant.org> Date: Mon, 27 Jan 2025 13:40:20 +0100 Subject: [PATCH 3/6] write unit test --- brian_dashboard_manager/templating/helpers.py | 1 + test/test_update.py | 143 ++++++++++++++++-- 2 files changed, 133 insertions(+), 11 deletions(-) diff --git a/brian_dashboard_manager/templating/helpers.py b/brian_dashboard_manager/templating/helpers.py index e3f58ac..4a3aff6 100644 --- a/brian_dashboard_manager/templating/helpers.py +++ b/brian_dashboard_manager/templating/helpers.py @@ -569,6 +569,7 @@ def get_router_dashboard_data(interfaces): 'hostname': host }) + # return dict(sorted(result.items(),key=lambda item: item[0])) return result diff --git a/test/test_update.py b/test/test_update.py index ba02ff7..f6a955b 100644 --- a/test/test_update.py +++ b/test/test_update.py @@ -11,7 +11,8 @@ TEST_INTERFACES = [ "name": "ge-0/0/8", "bundle": [], "bundle-parents": [], - "description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone", # noqa: E501 + "description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone", + # noqa: E501 "circuits": [ { "id": 679232, @@ -41,7 +42,8 @@ TEST_INTERFACES = [ "name": "ge-0/0/8.10", "bundle": [], "bundle-parents": [], - "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ", # noqa: E501 + "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ", + # noqa: E501 "circuits": [ { "id": 679360, @@ -75,7 +77,8 @@ TEST_INTERFACES = [ "name": "ge-0/0/8.11", "bundle": [], "bundle-parents": [], - "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF", # noqa: E501 + "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF", + # noqa: E501 "circuits": [ { "id": 712144, @@ -107,7 +110,8 @@ TEST_INTERFACES = [ "name": "ge-0/0/8.12", "bundle": [], "bundle-parents": [], - "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN", # noqa: E501 + "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN", + # noqa: E501 "circuits": [ { "id": 678920, @@ -139,7 +143,8 @@ TEST_INTERFACES = [ "name": "ge-0/0/8.996", "bundle": [], "bundle-parents": [], - "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab", # noqa: E501 + "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab", + # noqa: E501 "circuits": [ { "id": 678999, @@ -725,14 +730,14 @@ def populate_inventory(get_test_data, data_config): ("NREN Access", [], {'ASNET-AM', 'CESNET', 'GEANT', 'KIAE', 'LITNET', 'SWITCH'}), ("NREN Access", ["GEANT", "KIAE"], {'ASNET-AM', 'CESNET', 'LITNET', 'SWITCH'}), ( - "NREN Access", - [], - {'ASNET-AM', "LITNET", "CESNET", "GEANT", "KIAE", "SWITCH"}, + "NREN Access", + [], + {'ASNET-AM', "LITNET", "CESNET", "GEANT", "KIAE", "SWITCH"}, ), ( - "NREN Access", - ["GEANT"], - {'ASNET-AM', "LITNET", "CESNET", "KIAE", "SWITCH"}, + "NREN Access", + ["GEANT"], + {'ASNET-AM', "LITNET", "CESNET", "KIAE", "SWITCH"}, ), ("testfolder", ["GEANT"], {"KIAE", "SWITCH"}), ], @@ -891,6 +896,122 @@ def test_provision_re_peer_dashboard( assert len(panels[-1]['panels'][0]) > 0 +@responses.activate +def test_vlan_interfaces(mocker, data_config, mock_grafana, reporting_provider, populate_inventory + ): + interfaces = [ + {'bundle': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], + 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [], + 'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}, 'dashboards': ['NREN', 'RE_CUST'], + 'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}], + 'description': 'LAG CUSTOMER REDIRIS SRF21114 $GA-01800 |', 'ipv4': [], 'ipv6': [], 'name': 'ae16', + 'port_type': 'ACCESS', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 654, 'vlan_type': 'TRUNK'}, + + {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ + {'id': 739804, 'name': 'UC3M-REDIRIS-BELNET-SLICES-IMEC', 'status': 'non-monitored', 'type': 'GEANT PLUS'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, + 'dashboards': ["VLAN Interfaces"], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, + {'interface_type': 'LOGICAL', 'name': 'BELNET'}], + 'description': 'SRV_L2CIRCUIT CUSTOMER REDIRIS BELNET #UC3M-RedIRIS-BELNET-SLICES-IMEC $GS-02514 |', + 'ipv4': [], 'ipv6': [], 'name': 'ae16.975', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', + 'snmp-index': 818, 'vlan_type': 'VLAN'}, + + {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ + {'id': 732759, 'name': 'FRA-MAD-RARE-REDIRIS-23017-VL201', 'status': 'non-monitored', + 'type': 'GEANT PLUS'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'RARE'}, + 'dashboards': ['L2_CIRCUIT'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'RARE'}, + {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}], + 'description': 'SRV_L2CIRCUIT CUSTOMER RARE REDIRIS #fra-mad-RARE-REDIRIS-23017-VL201 $GS-02274', 'ipv4': [], + 'ipv6': [], 'name': 'ae16.201', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 642, + 'vlan_type': 'VLAN'}, + + {'bundle': [], 'bundle-parents': [], 'circuits': [ + {'id': 729417, 'name': 'PAR-LON2-SUPERPOP-QFX-2-GEANT', 'status': 'operational', 'type': 'GEANT - GBS'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}, 'dashboards': ['GBS_10G'], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}], + 'description': 'SRV_10GGBS CUSTOMER GEANT-IT #par-lon2-SUPERPOP-QFX-2-GEANT $GS-00081 |', 'ipv4': [], + 'ipv6': [], 'name': 'xe-2/2/7.0', 'port_type': 'SERVICE', 'router': 'mx1.lon2.uk.geant.net', 'snmp-index': 613, + 'vlan_type': 'VLAN'}, + + {'bundle': ['xe-0/1/0', 'xe-0/1/1'], 'bundle-parents': ['xe-0/1/0', 'xe-0/1/1'], 'circuits': [], + 'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'LITNET'}, 'dashboards': ['NREN', 'RE_CUST'], + 'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'LITNET'}], + 'description': 'LAG CUSTOMER LITNET AP2 #LITNET-AP2-LAG $GA-02071 |', 'ipv4': [], 'ipv6': [], 'name': 'ae10', + 'port_type': 'ACCESS', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 588, 'vlan_type': 'TRUNK'}, + + {'bundle': [], 'bundle-parents': ['et-0/0/2'], 'circuits': [ + {'id': 679356, 'name': 'LAT-AP1-IPV6', 'status': 'operational', 'type': 'GEANT IP'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'LAT'}, + 'dashboards': ['NREN', 'RE_CUST'], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'LAT'}], + 'description': 'SRV_GLOBAL CUSTOMER LAT #LAT-AP1 $GS-00484 | ASN5538', + 'ipv4': ['62.40.124.237/30'], 'ipv6': ['2001:798:99:1::51/126'], 'name': 'ae10.83', + 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 604, + 'vlan_type': 'VLAN'}, + + {'bundle': [], 'bundle-parents': ['et-2/1/2', 'et-2/1/5', 'et-11/1/0'], 'circuits': [ + {'id': 707643, 'name': 'GARR-UDMILANO_EXPRESSROUTE_VLAN4086', 'status': 'operational', + 'type': 'EXPRESS ROUTE'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GARR'}, + 'dashboards': ['GCS'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GARR'}], + 'description': 'SRV_GCS CUSTOMER GARR MICROSOFT #GARR-UDMilano_ExpressRoute_Vlan4086 $GS-01148 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED', + 'ipv4': [], 'ipv6': [], 'name': 'ae10.4086', 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', + 'snmp-index': 795, 'vlan_type': 'VLAN'}, + + {'bundle': [], 'bundle-parents': [], 'circuits': [], + 'dashboard_info': {'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}, 'dashboards': ['INFRASTRUCTURE_BACKBONE'], + 'dashboards_info': [{'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}], + 'description': 'PHY INFRASTRUCTURE BACKBONE P_ae5 | BUD-ZAG', 'ipv4': [], 'ipv6': [], 'name': 'et-7/0/2', + 'port_type': 'UNKNOWN', 'router': 'mx1.bud.hu.geant.net', 'snmp-index': 1133, 'vlan_type': 'ACCESS'}, + + ] + populate_inventory( + { + "/poller/interfaces": interfaces, + "/data/interfaces": interfaces, + "/poller/eumetsat-multicast": EUMETSAT_MULTICAST, + "/poller/regions": NREN_REGIONS, + } + ) + _mocked_gws = mocker.patch( + "brian_dashboard_manager.grafana.provision.get_gws_direct" + ) + _mocked_gws.return_value = [] + + _mocked_gws_indirect = mocker.patch( + "brian_dashboard_manager.grafana.provision.get_gws_indirect" + ) + _mocked_gws_indirect.return_value = [] + + # _mocked_vlan_data = mocker.patch( + # "brian_dashboard_manager.grafana.provision.get_router_dashboard_data" + # ) + # _mocked_vlan_data.return_value = [] + # + # _mocked_dashboard_data_dropdown = mocker.patch( + # "brian_dashboard_manager.grafana.provision.get_dashboard_data_dropdown" + # ) + # _mocked_dashboard_data_dropdown.return_value = [] + + data_config["organizations"] = [ + {"name": "Testorg1", "excluded_nrens": ["GEANT"], "excluded_dashboards": []}, + ] + provision(data_config) + folder_uid = "VLAN_Interfaces" + # assert len(mock_grafana.folders[folder_uid]) == 1 + result = mock_grafana.dashboards_by_folder_uid[folder_uid] + assert len(result) == 3 + # assert result[0]["title"] == "art1.kau.lt.geant.net" + assert result[0]["tags"][0] == "vlandash" + panels = mock_grafana.dashboards_by_folder_uid[folder_uid][0]["panels"] + expected_types = ["text", "row"] + assert [p["type"] for p in panels] == expected_types + assert "INFO" in panels[0]["options"]["content"] + # assert "ae10" in panels[1]["title"] + # assert len(panels[1]["panels"]) == 3 + + + @responses.activate @pytest.mark.parametrize( "folder_name, dashboard_id, expected_dashboard_count", -- GitLab From 9e9bad69850829802ee5c7171b1061d91ee971e0 Mon Sep 17 00:00:00 2001 From: Bjarke Madsen <bjarke@nordu.net> Date: Thu, 30 Jan 2025 10:04:52 +0100 Subject: [PATCH 4/6] Fix test due to threading --- test/test_update.py | 187 +++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 107 deletions(-) diff --git a/test/test_update.py b/test/test_update.py index f6a955b..688afe2 100644 --- a/test/test_update.py +++ b/test/test_update.py @@ -1,3 +1,4 @@ +# flake8: noqa import pytest import responses from concurrent.futures import ThreadPoolExecutor @@ -12,7 +13,6 @@ TEST_INTERFACES = [ "bundle": [], "bundle-parents": [], "description": "PHY CUSTOMER GEANT CORPORATE SRF000001 | GEANT Corporate to MX1.LON - Via Vodafone", - # noqa: E501 "circuits": [ { "id": 679232, @@ -43,7 +43,6 @@ TEST_INTERFACES = [ "bundle": [], "bundle-parents": [], "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE-ViaVodafone | GEANT Corporate to mx1.lon - Via Vodafone ", - # noqa: E501 "circuits": [ { "id": 679360, @@ -78,7 +77,6 @@ TEST_INTERFACES = [ "bundle": [], "bundle-parents": [], "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF | GEANT Corporate to mx1.lon - Via Vodafone - for VRF", - # noqa: E501 "circuits": [ { "id": 712144, @@ -111,11 +109,10 @@ TEST_INTERFACES = [ "bundle": [], "bundle-parents": [], "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_CORPORATE_ViaVodafone-VRF-TEST | GEANT Corporate to mx1.lon - Via Vodafone - DASHBOARD BGP TEST VLAN", - # noqa: E501 "circuits": [ { "id": 678920, - "name": "GEANT_CORPORATE_VIAVODAFONE-VRF-TEST (DO NOT OPEN A TICKET)", # noqa: E501 + "name": "GEANT_CORPORATE_VIAVODAFONE-VRF-TEST (DO NOT OPEN A TICKET)", "type": "GEANT IP", "status": "non-monitored" } @@ -144,7 +141,6 @@ TEST_INTERFACES = [ "bundle": [], "bundle-parents": [], "description": "SRV_GLOBAL CUSTOMER GEANT #GEANT_OPERATIONS_LabConnectivity | GEANT MX1.LON Infinera VRF to Operations Lab", - # noqa: E501 "circuits": [ { "id": 678999, @@ -226,7 +222,7 @@ TEST_INTERFACES = [ "name": "ge-0/2/1.0", "bundle": [], "bundle-parents": [], - "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-ZAG OPENFLOW |", # noqa: E501 + "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-ZAG OPENFLOW |", "circuits": [], "snmp-index": 687, "dashboards": [ @@ -248,7 +244,7 @@ TEST_INTERFACES = [ "name": "ge-0/2/2.0", "bundle": [], "bundle-parents": [], - "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-VIE OPENFLOW |", # noqa: E501 + "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-VIE OPENFLOW |", "circuits": [], "snmp-index": 711, "dashboards": [ @@ -270,7 +266,7 @@ TEST_INTERFACES = [ "name": "ge-0/2/4.0", "bundle": [], "bundle-parents": [], - "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-FRA OPENFLOW |", # noqa: E501 + "description": "SRV_L2CIRCUIT INFRASTRUCTURE GEANT GEANT #AMS-FRA OPENFLOW |", "circuits": [], "snmp-index": 718, "dashboards": [ @@ -288,7 +284,6 @@ TEST_INTERFACES = [ "ipv6": [] }, { - "router": "rt1.fra.de.geant.net", "name": "xe-11/2/5.300", "bundle": [], @@ -331,7 +326,7 @@ NREN_INTERFACES = [ "ae10" ], "bundle-parents": [], - "description": "PHY CUSTOMER HEANET P_AE10 SRF9948758 | HEANET-AP2-LL3", # noqa: E501 + "description": "PHY CUSTOMER HEANET P_AE10 SRF9948758 | HEANET-AP2-LL3", "circuits": [], "snmp-index": 554, "dashboards": [ @@ -356,7 +351,7 @@ NREN_INTERFACES = [ "ae10" ], "bundle-parents": [], - "description": "PHY CUSTOMER HEANET P_AE10 SRF0000001 | HEANET-AP2-LL2", # noqa: E501 + "description": "PHY CUSTOMER HEANET P_AE10 SRF0000001 | HEANET-AP2-LL2", "circuits": [], "snmp-index": 527, "dashboards": [ @@ -381,7 +376,7 @@ NREN_INTERFACES = [ "ae10" ], "bundle-parents": [], - "description": "PHY CUSTOMER HEANET P_AE10 SRF9925903 | HEANET-AP2-LL1", # noqa: E501 + "description": "PHY CUSTOMER HEANET P_AE10 SRF9925903 | HEANET-AP2-LL1", "circuits": [], "snmp-index": 528, "dashboards": [ @@ -473,7 +468,7 @@ NREN_INTERFACES = [ "xe-1/0/1", "xe-1/1/0" ], - "description": "SRV_MDVPN CUSTOMER HEANET AP2 #HEANET-BGP-LU-CoC-1 |", # noqa: E501 + "description": "SRV_MDVPN CUSTOMER HEANET AP2 #HEANET-BGP-LU-CoC-1 |", "circuits": [ { "id": 663160, @@ -509,7 +504,7 @@ NREN_INTERFACES = [ "xe-1/0/1", "xe-1/1/0" ], - "description": "SRV_IAS CUSTOMER HEANET #HEANET-AP2-IAS IASPS | ASN1213 ", # noqa: E501 + "description": "SRV_IAS CUSTOMER HEANET #HEANET-AP2-IAS IASPS | ASN1213 ", "circuits": [ { "id": 663214, @@ -547,7 +542,7 @@ NREN_INTERFACES = [ "xe-1/0/1", "xe-1/1/0" ], - "description": "SRV_L2CIRCUIT CUSTOMER HEANET GEANT #ams-dub2-HEANET-RARE-21061 |", # noqa: E501 + "description": "SRV_L2CIRCUIT CUSTOMER HEANET GEANT #ams-dub2-HEANET-RARE-21061 |", "circuits": [ { "id": 713335, @@ -574,9 +569,7 @@ NREN_INTERFACES = [ "ipv4": [], "ipv6": [] }, - { - - "router": "rt1.fra.de.geant.net", + {"router": "rt1.fra.de.geant.net", "name": "xe-11/2/5.300", "bundle": [], "bundle-parents": [], @@ -607,48 +600,48 @@ NREN_INTERFACES = [ "port_type": "SERVICE", "ipv4": [], "ipv6": [] - } + } ] EUMETSAT_MULTICAST = [ { 'router': 'mx1.ams.nl.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.1', 'endpoint': '193.17.9.3' }, { 'router': 'mx1.ams.nl.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.2', 'endpoint': '193.17.9.3' }, { 'router': 'mx1.lon.uk.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.1', 'endpoint': '193.17.9.3' }, { 'router': 'mx1.lon.uk.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.2', 'endpoint': '193.17.9.3' }, { 'router': 'mx1.fra.de.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.1.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.1', 'endpoint': '193.17.9.3' }, { 'router': 'mx1.fra.de.geant.net', - 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', # noqa: E501 + 'oid': '1.3.6.1.2.1.83.1.1.2.1.16.232.223.222.2.193.17.9.3.255.255.255.255', 'community': '0pBiFbD', 'subscription': '232.223.222.2', 'endpoint': '193.17.9.3' @@ -730,14 +723,14 @@ def populate_inventory(get_test_data, data_config): ("NREN Access", [], {'ASNET-AM', 'CESNET', 'GEANT', 'KIAE', 'LITNET', 'SWITCH'}), ("NREN Access", ["GEANT", "KIAE"], {'ASNET-AM', 'CESNET', 'LITNET', 'SWITCH'}), ( - "NREN Access", - [], - {'ASNET-AM', "LITNET", "CESNET", "GEANT", "KIAE", "SWITCH"}, + "NREN Access", + [], + {'ASNET-AM', "LITNET", "CESNET", "GEANT", "KIAE", "SWITCH"}, ), ( - "NREN Access", - ["GEANT"], - {'ASNET-AM', "LITNET", "CESNET", "KIAE", "SWITCH"}, + "NREN Access", + ["GEANT"], + {'ASNET-AM', "LITNET", "CESNET", "KIAE", "SWITCH"}, ), ("testfolder", ["GEANT"], {"KIAE", "SWITCH"}), ], @@ -853,7 +846,7 @@ def test_provision_re_peer_dashboard( { "router": "mx1.dub2.ie.geant.net", "name": "xe-0/0/0.1", - "description": "PHY SVC P_AE10 SRF9948758 | HEANET-AP2-LL3", # noqa: E501 + "description": "PHY SVC P_AE10 SRF9948758 | HEANET-AP2-LL3", "dashboards": ["RE_PEER"], "dashboard_info": {"name": "ESNET", "interface_type": "LOGICAL"}, "dashboards_info": [{"name": "ESNET", "interface_type": "LOGICAL"}], @@ -905,64 +898,50 @@ def test_vlan_interfaces(mocker, data_config, mock_grafana, reporting_provider, 'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}, 'dashboards': ['NREN', 'RE_CUST'], 'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'REDIRIS'}], 'description': 'LAG CUSTOMER REDIRIS SRF21114 $GA-01800 |', 'ipv4': [], 'ipv6': [], 'name': 'ae16', - 'port_type': 'ACCESS', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 654, 'vlan_type': 'TRUNK'}, - - {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ - {'id': 739804, 'name': 'UC3M-REDIRIS-BELNET-SLICES-IMEC', 'status': 'non-monitored', 'type': 'GEANT PLUS'}], - 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, - 'dashboards': ["VLAN Interfaces"], - 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, - {'interface_type': 'LOGICAL', 'name': 'BELNET'}], - 'description': 'SRV_L2CIRCUIT CUSTOMER REDIRIS BELNET #UC3M-RedIRIS-BELNET-SLICES-IMEC $GS-02514 |', - 'ipv4': [], 'ipv6': [], 'name': 'ae16.975', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', - 'snmp-index': 818, 'vlan_type': 'VLAN'}, - - {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ - {'id': 732759, 'name': 'FRA-MAD-RARE-REDIRIS-23017-VL201', 'status': 'non-monitored', - 'type': 'GEANT PLUS'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'RARE'}, - 'dashboards': ['L2_CIRCUIT'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'RARE'}, - {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}], - 'description': 'SRV_L2CIRCUIT CUSTOMER RARE REDIRIS #fra-mad-RARE-REDIRIS-23017-VL201 $GS-02274', 'ipv4': [], - 'ipv6': [], 'name': 'ae16.201', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 642, - 'vlan_type': 'VLAN'}, - - {'bundle': [], 'bundle-parents': [], 'circuits': [ - {'id': 729417, 'name': 'PAR-LON2-SUPERPOP-QFX-2-GEANT', 'status': 'operational', 'type': 'GEANT - GBS'}], - 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}, 'dashboards': ['GBS_10G'], - 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}], - 'description': 'SRV_10GGBS CUSTOMER GEANT-IT #par-lon2-SUPERPOP-QFX-2-GEANT $GS-00081 |', 'ipv4': [], - 'ipv6': [], 'name': 'xe-2/2/7.0', 'port_type': 'SERVICE', 'router': 'mx1.lon2.uk.geant.net', 'snmp-index': 613, - 'vlan_type': 'VLAN'}, - - {'bundle': ['xe-0/1/0', 'xe-0/1/1'], 'bundle-parents': ['xe-0/1/0', 'xe-0/1/1'], 'circuits': [], - 'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'LITNET'}, 'dashboards': ['NREN', 'RE_CUST'], - 'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'LITNET'}], - 'description': 'LAG CUSTOMER LITNET AP2 #LITNET-AP2-LAG $GA-02071 |', 'ipv4': [], 'ipv6': [], 'name': 'ae10', - 'port_type': 'ACCESS', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 588, 'vlan_type': 'TRUNK'}, - - {'bundle': [], 'bundle-parents': ['et-0/0/2'], 'circuits': [ - {'id': 679356, 'name': 'LAT-AP1-IPV6', 'status': 'operational', 'type': 'GEANT IP'}], - 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'LAT'}, - 'dashboards': ['NREN', 'RE_CUST'], - 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'LAT'}], - 'description': 'SRV_GLOBAL CUSTOMER LAT #LAT-AP1 $GS-00484 | ASN5538', - 'ipv4': ['62.40.124.237/30'], 'ipv6': ['2001:798:99:1::51/126'], 'name': 'ae10.83', - 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 604, - 'vlan_type': 'VLAN'}, - - {'bundle': [], 'bundle-parents': ['et-2/1/2', 'et-2/1/5', 'et-11/1/0'], 'circuits': [ - {'id': 707643, 'name': 'GARR-UDMILANO_EXPRESSROUTE_VLAN4086', 'status': 'operational', - 'type': 'EXPRESS ROUTE'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GARR'}, - 'dashboards': ['GCS'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GARR'}], - 'description': 'SRV_GCS CUSTOMER GARR MICROSOFT #GARR-UDMilano_ExpressRoute_Vlan4086 $GS-01148 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED', - 'ipv4': [], 'ipv6': [], 'name': 'ae10.4086', 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', - 'snmp-index': 795, 'vlan_type': 'VLAN'}, - - {'bundle': [], 'bundle-parents': [], 'circuits': [], - 'dashboard_info': {'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}, 'dashboards': ['INFRASTRUCTURE_BACKBONE'], - 'dashboards_info': [{'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}], - 'description': 'PHY INFRASTRUCTURE BACKBONE P_ae5 | BUD-ZAG', 'ipv4': [], 'ipv6': [], 'name': 'et-7/0/2', - 'port_type': 'UNKNOWN', 'router': 'mx1.bud.hu.geant.net', 'snmp-index': 1133, 'vlan_type': 'ACCESS'}, + 'port_type': 'ACCESS', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 654, 'vlan_type': 'TRUNK'}, {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ + {'id': 739804, 'name': 'UC3M-REDIRIS-BELNET-SLICES-IMEC', 'status': 'non-monitored', 'type': 'GEANT PLUS'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, + 'dashboards': ["VLAN Interfaces"], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'REDIRIS'}, + {'interface_type': 'LOGICAL', 'name': 'BELNET'}], + 'description': 'SRV_L2CIRCUIT CUSTOMER REDIRIS BELNET #UC3M-RedIRIS-BELNET-SLICES-IMEC $GS-02514 |', + 'ipv4': [], 'ipv6': [], 'name': 'ae16.975', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', + 'snmp-index': 818, 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': ['et-4/0/0', 'et-5/0/5', 'et-8/1/2', 'et-8/1/5'], 'circuits': [ + {'id': 732759, 'name': 'FRA-MAD-RARE-REDIRIS-23017-VL201', 'status': 'non-monitored', + 'type': 'GEANT PLUS'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'RARE'}, + 'dashboards': ['L2_CIRCUIT'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'RARE'}, + {'interface_type': 'LOGICAL', 'name': 'REDIRIS'}], + 'description': 'SRV_L2CIRCUIT CUSTOMER RARE REDIRIS #fra-mad-RARE-REDIRIS-23017-VL201 $GS-02274', 'ipv4': [], + 'ipv6': [], 'name': 'ae16.201', 'port_type': 'SERVICE', 'router': 'mx1.mad.es.geant.net', 'snmp-index': 642, + 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': [], 'circuits': [ + {'id': 729417, 'name': 'PAR-LON2-SUPERPOP-QFX-2-GEANT', 'status': 'operational', 'type': 'GEANT - GBS'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}, 'dashboards': ['GBS_10G'], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GEANT-IT'}], + 'description': 'SRV_10GGBS CUSTOMER GEANT-IT #par-lon2-SUPERPOP-QFX-2-GEANT $GS-00081 |', 'ipv4': [], + 'ipv6': [], 'name': 'xe-2/2/7.0', 'port_type': 'SERVICE', 'router': 'mx1.lon2.uk.geant.net', 'snmp-index': 613, + 'vlan_type': 'VLAN'}, {'bundle': ['xe-0/1/0', 'xe-0/1/1'], 'bundle-parents': ['xe-0/1/0', 'xe-0/1/1'], 'circuits': [], + 'dashboard_info': {'interface_type': 'AGGREGATE', 'name': 'LITNET'}, 'dashboards': ['NREN', 'RE_CUST'], + 'dashboards_info': [{'interface_type': 'AGGREGATE', 'name': 'LITNET'}], + 'description': 'LAG CUSTOMER LITNET AP2 #LITNET-AP2-LAG $GA-02071 |', 'ipv4': [], 'ipv6': [], 'name': 'ae10', + 'port_type': 'ACCESS', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 588, 'vlan_type': 'TRUNK'}, {'bundle': [], 'bundle-parents': ['et-0/0/2'], 'circuits': [ + {'id': 679356, 'name': 'LAT-AP1-IPV6', 'status': 'operational', 'type': 'GEANT IP'}], + 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'LAT'}, + 'dashboards': ['NREN', 'RE_CUST'], + 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'LAT'}], + 'description': 'SRV_GLOBAL CUSTOMER LAT #LAT-AP1 $GS-00484 | ASN5538', + 'ipv4': ['62.40.124.237/30'], 'ipv6': ['2001:798:99:1::51/126'], 'name': 'ae10.83', + 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', 'snmp-index': 604, + 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': ['et-2/1/2', 'et-2/1/5', 'et-11/1/0'], 'circuits': [ + {'id': 707643, 'name': 'GARR-UDMILANO_EXPRESSROUTE_VLAN4086', 'status': 'operational', + 'type': 'EXPRESS ROUTE'}], 'dashboard_info': {'interface_type': 'LOGICAL', 'name': 'GARR'}, + 'dashboards': ['GCS'], 'dashboards_info': [{'interface_type': 'LOGICAL', 'name': 'GARR'}], + 'description': 'SRV_GCS CUSTOMER GARR MICROSOFT #GARR-UDMilano_ExpressRoute_Vlan4086 $GS-01148 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED', + 'ipv4': [], 'ipv6': [], 'name': 'ae10.4086', 'port_type': 'SERVICE', 'router': 'art1.kau.lt.geant.net', + 'snmp-index': 795, 'vlan_type': 'VLAN'}, {'bundle': [], 'bundle-parents': [], 'circuits': [], + 'dashboard_info': {'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}, 'dashboards': ['INFRASTRUCTURE_BACKBONE'], + 'dashboards_info': [{'interface_type': 'PHYSICAL', 'name': 'BUD-ZAG'}], + 'description': 'PHY INFRASTRUCTURE BACKBONE P_ae5 | BUD-ZAG', 'ipv4': [], 'ipv6': [], 'name': 'et-7/0/2', + 'port_type': 'UNKNOWN', 'router': 'mx1.bud.hu.geant.net', 'snmp-index': 1133, 'vlan_type': 'ACCESS'}, ] populate_inventory( @@ -983,33 +962,27 @@ def test_vlan_interfaces(mocker, data_config, mock_grafana, reporting_provider, ) _mocked_gws_indirect.return_value = [] - # _mocked_vlan_data = mocker.patch( - # "brian_dashboard_manager.grafana.provision.get_router_dashboard_data" - # ) - # _mocked_vlan_data.return_value = [] - # - # _mocked_dashboard_data_dropdown = mocker.patch( - # "brian_dashboard_manager.grafana.provision.get_dashboard_data_dropdown" - # ) - # _mocked_dashboard_data_dropdown.return_value = [] - data_config["organizations"] = [ {"name": "Testorg1", "excluded_nrens": ["GEANT"], "excluded_dashboards": []}, ] provision(data_config) folder_uid = "VLAN_Interfaces" - # assert len(mock_grafana.folders[folder_uid]) == 1 + result = mock_grafana.dashboards_by_folder_uid[folder_uid] assert len(result) == 3 - # assert result[0]["title"] == "art1.kau.lt.geant.net" + assert result[0]["tags"][0] == "vlandash" - panels = mock_grafana.dashboards_by_folder_uid[folder_uid][0]["panels"] - expected_types = ["text", "row"] + dashboards = mock_grafana.dashboards_by_folder_uid[folder_uid] + panels = [] + for dashboard in dashboards: + panels.extend(dashboard["panels"]) + expected_types = ["text", "row", "text", "row", "text", "row"] assert [p["type"] for p in panels] == expected_types assert "INFO" in panels[0]["options"]["content"] - # assert "ae10" in panels[1]["title"] - # assert len(panels[1]["panels"]) == 3 + assert "ae10" in set(p['title'] for p in panels) + panel_ae10 = [p for p in panels if p['title'] == 'ae10'][0] + assert len(panel_ae10["panels"]) == 3 @responses.activate -- GitLab From 8bdad9211d498c6443fe935eb1e88fa67d79faf3 Mon Sep 17 00:00:00 2001 From: Maryam Mokhtarifar <maryam.mokhtarifar@geant.org> Date: Thu, 30 Jan 2025 10:17:18 +0100 Subject: [PATCH 5/6] remove unused code --- brian_dashboard_manager/templating/helpers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/brian_dashboard_manager/templating/helpers.py b/brian_dashboard_manager/templating/helpers.py index 4a3aff6..e3f58ac 100644 --- a/brian_dashboard_manager/templating/helpers.py +++ b/brian_dashboard_manager/templating/helpers.py @@ -569,7 +569,6 @@ def get_router_dashboard_data(interfaces): 'hostname': host }) - # return dict(sorted(result.items(),key=lambda item: item[0])) return result -- GitLab From b8f41a7c7ae5c1acbd60e1da52640a3a7aea4c86 Mon Sep 17 00:00:00 2001 From: Bjarke Madsen <bjarke@nordu.net> Date: Thu, 30 Jan 2025 13:43:10 +0100 Subject: [PATCH 6/6] Add VLAN Interfaces to excluded folders --- brian_dashboard_manager/config.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/brian_dashboard_manager/config.py b/brian_dashboard_manager/config.py index eab8871..00546a6 100644 --- a/brian_dashboard_manager/config.py +++ b/brian_dashboard_manager/config.py @@ -58,7 +58,8 @@ DEFAULT_ORGANIZATIONS = [ "excluded_folders": { "Aggregates": ["CAE1"], "EUMETSAT Multicast": True, - "NREN Access LEGACY": True + "NREN Access LEGACY": True, + "VLAN Interfaces": True, } }, { @@ -90,7 +91,8 @@ DEFAULT_ORGANIZATIONS = [ "GWS Direct": True, "GWS Indirect": True, "EUMETSAT Multicast": True, - "NREN Access LEGACY": True + "NREN Access LEGACY": True, + "VLAN Interfaces": True, } }, { @@ -111,7 +113,8 @@ DEFAULT_ORGANIZATIONS = [ ], "excluded_folders": { "EUMETSAT Multicast": True, - "NREN Access LEGACY": True + "NREN Access LEGACY": True, + "VLAN Interfaces": True, } }, { @@ -141,7 +144,8 @@ DEFAULT_ORGANIZATIONS = [ "IAS UPSTREAM": True, "GWS PHY Upstream": True, "EUMETSAT Multicast": True, - "NREN Access LEGACY": True + "NREN Access LEGACY": True, + "VLAN Interfaces": True, } } ] -- GitLab