diff --git a/inventory_provider/routes/poller.py b/inventory_provider/routes/poller.py index 0344dbacaf4fad3aa3982bb7e39bb80a190ac500..10122a6727b042c6019f278b08c78c45cb89b404 100644 --- a/inventory_provider/routes/poller.py +++ b/inventory_provider/routes/poller.py @@ -75,6 +75,13 @@ routes = Blueprint('poller-support-routes', __name__) Gb = 1 << 30 +class INTERFACE_TYPES(Enum): + UNKNOWN = auto() + LOGICAL = auto() + PHYSICAL = auto() + AGGREGATE = auto() + + class BRIAN_DASHBOARDS(Enum): CLS = auto() RE_PEER = auto() @@ -99,10 +106,15 @@ class BRIAN_DASHBOARDS(Enum): LHCONE = auto() CAE1 = auto() + # NREN customer + NREN = auto() + # only used in INTERFACE_LIST_SCHEMA and sphinx docs _DASHBOARD_IDS = [d.name for d in list(BRIAN_DASHBOARDS)] +_INTERFACE_TYPES = [i.name for i in list(INTERFACE_TYPES)] + INTERFACE_LIST_SCHEMA = { '$schema': 'http://json-schema.org/draft-07/schema#', @@ -143,6 +155,15 @@ INTERFACE_LIST_SCHEMA = { 'dashboards': { 'type': 'array', 'items': {'enum': _DASHBOARD_IDS} + }, + 'dashboard_info': { + 'type': 'object', + 'properties': { + 'name': {'type': 'string'}, + 'interface_type': {'enum': _INTERFACE_TYPES} + }, + 'required': ['name', 'interface_type'], + 'additionalProperties': False } }, 'required': [ @@ -371,7 +392,7 @@ def _get_dashboards(interface): yield BRIAN_DASHBOARDS.IAS_UPSTREAM if 'SRV_GLOBAL RE_INTERCONNECT' in description: yield BRIAN_DASHBOARDS.RE_PEER - if re.match('(PHY|LAG|SRV_GLOBAL) CUSTOMER', description): + if re.match(r'(PHY|LAG|SRV_GLOBAL) CUSTOMER', description): yield BRIAN_DASHBOARDS.RE_CUST if re.match('^SRV_GCS', description): yield BRIAN_DASHBOARDS.GCS @@ -397,6 +418,45 @@ def _get_dashboards(interface): yield BRIAN_DASHBOARDS.CAE1 if re.match('^PHY UPSTREAM', description): yield BRIAN_DASHBOARDS.GWS_PHY_UPSTREAM + regex = r'(PHY|LAG|(SRV_(GLOBAL|LHCONE|MDVPN|IAS|CLS|L3VPN))) CUSTOMER' + if re.match(regex, description): + yield BRIAN_DASHBOARDS.NREN + + +def _get_dashboard_data(ifc): + + def _get_interface_type(description): + if re.match(r'^PHY', description): + return INTERFACE_TYPES.PHYSICAL + if re.match(r'^SRV_', description): + return INTERFACE_TYPES.LOGICAL + if re.match(r'^LAG', description): + return INTERFACE_TYPES.AGGREGATE + + return INTERFACE_TYPES.UNKNOWN + + description = ifc.get('description', '').strip() + dashboards = ifc.get('dashboards', []) + + interface_type = _get_interface_type(description) + + if len(dashboards) == 0: + return ifc + + if BRIAN_DASHBOARDS.INFRASTRUCTURE_BACKBONE.name in dashboards: + name = description.split('|') + name = name[1].strip() + name = name.replace('( ', '(') + else: + name = description.split(' ')[2].upper() + + return { + **ifc, + 'dashboard_info': { + 'name': name, + 'interface_type': interface_type.name + } + } def _add_dashboards(interfaces): @@ -410,7 +470,7 @@ def _add_dashboards(interfaces): for ifc in interfaces: dashboards = _get_dashboards(ifc) ifc['dashboards'] = sorted([d.name for d in dashboards]) - yield ifc + yield _get_dashboard_data(ifc) def _load_interface_bundles(hostname=None): @@ -778,9 +838,9 @@ def eumetsat_multicast(hostname=None): MX1_FRA = 'mx1.fra.de.geant.net' SUBSCRIPTIONS = [{ - 'subscription': f'232.223.222.{idx}', - 'endpoint': '193.17.9.3', - } for idx in range(1, 73)] + 'subscription': f'232.223.222.{idx}', + 'endpoint': '193.17.9.3', + } for idx in range(1, 73)] SUBSCRIPTIONS.append( {'subscription': '232.223.223.1', 'endpoint': '193.17.9.7'}) diff --git a/test/test_general_poller_routes.py b/test/test_general_poller_routes.py index 8774542b32677408d5b039cf03d8fd71cf9be39a..7370c36cc0a2d1a1300e02f87f1c7a535a4d2e9d 100644 --- a/test/test_general_poller_routes.py +++ b/test/test_general_poller_routes.py @@ -55,7 +55,7 @@ def test_eumetsat_multicast(mocker, client): # routers don't have snmp acl's for us mocker.patch('inventory_provider.juniper.snmp_community_string') \ - .return_value = 'blah' + .return_value = 'blah' rv = client.get( '/poller/eumetsat-multicast', @@ -219,9 +219,31 @@ def test_fw_counter_bytes_oid_values(customer, interface_name, expected_oid): @pytest.mark.parametrize('description,expected_dashboards', [ ('SRV_IAS CUSTOMER JISC #JISC-AP1-IAS IASPS | ASN786', - ['IAS_CUSTOMER']), + ['IAS_CUSTOMER', 'NREN']), ('SRV_L2CIRCUIT CUSTOMER JISC JISC #DUB-LON-NRENBBEXT-JANET-13015 | backup for niran ', # noqa: E501 - ['L2_CIRCUIT']) + ['L2_CIRCUIT']), + ('SRV_L3VPN CUSTOMER EENET #EENET-AP2-LHCONE | ASN3221', + ['LHCONE', 'LHCONE_CUST', 'NREN']), + ('SRV_IAS PRIVATE OPTIMA-TELEKOM #HR-EduZone | For Eduzone', + ['IAS_PEERS', 'IAS_PRIVATE']), + ('SRV_CLS PRIVATE AWS #AT-AWS-CLS|ASN16509 | ', + ['CLS', 'CLS_PEERS']), + ('SRV_IAS PUBLIC MIX #IX_Peerings_in_MIX |', + ['IAS_PEERS', 'IAS_PUBLIC']), + ('LAG INFRASTRUCTURE BACKBONE SRF0000001 | bil-por', + ['INFRASTRUCTURE_BACKBONE']), + ('SRV_GCS CUSTOMER FCCN MICROSOFT #FCCN_NoveSBE_ExpressRoute_Vlan1945 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED', # noqa: E501 + ['GCS']), + ('PHY UPSTREAM TELIA SRF9940473 | Telia ID: IC-326863', + ['GWS_PHY_UPSTREAM']), + ('SRV_IAS UPSTREAM COGENT #COGENT_GWS_VIE | ASN174', + ['IAS_UPSTREAM']), + ('SRV_L3VPN RE_INTERCONNECT CLARA #REDCLARA-LIS-LHCONE | ASN27750', + ['LHCONE', 'LHCONE_PEER']), + ('SRV_MDVPN CUSTOMER REDIRIS #RedIRIS_AP1_BGP_LU_CoC_1 | MD VPN CoC-REDIRIS - ', # noqa: E501 + ['MDVPN_CUSTOMERS', 'NREN']), + ('SRV_L2CIRCUIT CUSTOMER TENET PSNC #lon-lon-GEANTOPEN-PSNC-TENET-18067 |', # noqa: E501 + ['GEANTOPEN', 'L2_CIRCUIT']) ]) def test_interface_dashboard_mapping(description, expected_dashboards): interface = { @@ -232,3 +254,64 @@ def test_interface_dashboard_mapping(description, expected_dashboards): dashboards = poller._get_dashboards(interface) dashboards = [d.name for d in dashboards] assert set(list(dashboards)) == set(expected_dashboards) + + +@pytest.mark.parametrize('interface,dashboard_info', [ + ({ + 'description': 'SRV_IAS CUSTOMER JISC #JISC-AP1-IAS IASPS | ASN786', + 'dashboards': ['IAS_CUSTOMER', 'NREN'] + }, {'name': 'JISC', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_L2CIRCUIT CUSTOMER JISC JISC #DUB-LON-NRENBBEXT-JANET-13015 | backup for niran ', # noqa: E501 + 'dashboards': ['L2_CIRCUIT'] + }, {'name': 'JISC', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_L3VPN CUSTOMER EENET #EENET-AP2-LHCONE | ASN3221', + 'dashboards': ['LHCONE', 'LHCONE_CUST', 'NREN'] + }, {'name': 'EENET', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_IAS PRIVATE OPTIMA-TELEKOM #HR-EduZone | For Eduzone', # noqa: E501 + 'dashboards': ['IAS_PEERS', 'IAS_PRIVATE'] + }, {'name': 'OPTIMA-TELEKOM', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_CLS PRIVATE AWS #AT-AWS-CLS|ASN16509 | ', + 'dashboards': ['CLS', 'CLS_PEERS'] + }, {'name': 'AWS', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_IAS PUBLIC MIX #IX_Peerings_in_MIX |', + 'dashboards': ['IAS_PEERS', 'IAS_PUBLIC'] + }, {'name': 'MIX', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'LAG INFRASTRUCTURE BACKBONE SRF0000001 | bil-por', + 'dashboards': ['INFRASTRUCTURE_BACKBONE'] + }, {'name': 'bil-por', 'interface_type': 'AGGREGATE'}), + ({ + 'description': 'SRV_GCS CUSTOMER FCCN MICROSOFT #FCCN_NoveSBE_ExpressRoute_Vlan1945 | UNIT CONFIGURATION HAS BEEN SYSTEM GENERATED', # noqa: E501 + 'dashboards': ['GCS'] + }, {'name': 'FCCN', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'PHY UPSTREAM TELIA SRF9940473 | Telia ID: IC-326863', + 'dashboards': ['GWS_PHY_UPSTREAM'] + }, {'name': 'TELIA', 'interface_type': 'PHYSICAL'}), + ({ + 'description': 'SRV_IAS UPSTREAM COGENT #COGENT_GWS_VIE | ASN174', + 'dashboards': ['IAS_UPSTREAM'] + }, {'name': 'COGENT', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_L3VPN RE_INTERCONNECT CLARA #REDCLARA-LIS-LHCONE | ASN27750', # noqa: E501 + 'dashboards': ['LHCONE', 'LHCONE_PEER'] + }, {'name': 'CLARA', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_MDVPN CUSTOMER REDIRIS #RedIRIS_AP1_BGP_LU_CoC_1 | MD VPN CoC-REDIRIS - ', # noqa: E501 + 'dashboards': ['MDVPN_CUSTOMERS', 'NREN'] + }, {'name': 'REDIRIS', 'interface_type': 'LOGICAL'}), + ({ + 'description': 'SRV_L2CIRCUIT CUSTOMER TENET PSNC #lon-lon-GEANTOPEN-PSNC-TENET-18067 |', # noqa: E501 + 'dashboards': ['GEANTOPEN', 'L2_CIRCUIT'] + }, {'name': 'TENET', 'interface_type': 'LOGICAL'}), +]) +def test_description_dashboard_parsing(interface, dashboard_info): + + updated = poller._get_dashboard_data(interface) + info = updated['dashboard_info'] + assert info == dashboard_info diff --git a/tox.ini b/tox.ini index a583519e177d0ae4903e6d86a949427121ee6ee6..7d0d25df10b59e54c9a10b05c6cdee9fa24920da 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = py36 [flake8] -exclude = venv +exclude = venv,.tox [testenv] passenv = TEST_OPSDB_HOSTNAME TEST_OPSDB_DBNAME TEST_OPSDB_USERNAME TEST_OPSDB_PASSWORD