From 5243d531b7aa4c3696901ba21da8b55f5ce17324 Mon Sep 17 00:00:00 2001 From: Erik Reid <erik.reid@geant.org> Date: Sat, 27 Mar 2021 11:52:10 +0100 Subject: [PATCH] draft /poller/eumetsat-multicast handler --- inventory_provider/routes/poller.py | 109 ++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/inventory_provider/routes/poller.py b/inventory_provider/routes/poller.py index 79c3ec88..6c95ad68 100644 --- a/inventory_provider/routes/poller.py +++ b/inventory_provider/routes/poller.py @@ -3,6 +3,8 @@ import logging import re from flask import Blueprint, Response, current_app +from lxml import etree + from inventory_provider import juniper from inventory_provider.routes import common @@ -61,6 +63,7 @@ INTERFACE_LIST_SCHEMA = { 'items': {'$ref': '#/definitions/interface'} } + INTERFACE_SPEED_LIST_SCHEMA = { '$schema': 'http://json-schema.org/draft-07/schema#', @@ -81,6 +84,37 @@ INTERFACE_SPEED_LIST_SCHEMA = { 'items': {'$ref': '#/definitions/interface'} } +MULTICAST_SUBSCRIPTION_LIST_SCHEMA = { + '$schema': 'http://json-schema.org/draft-07/schema#', + + 'definitions': { + 'ipv4-address': { + 'type': 'string', + 'pattern': r'^(\d+\.){3}\d+$' + }, + 'subscription': { + 'type': 'object', + 'properties': { + 'router': {'type': 'string'}, + 'subscription': {'$ref': '#/definitions/ipv4-address'}, + 'endpoint': {'$ref': '#/definitions/ipv4-address'}, + 'oid': { + 'type': 'string', + 'pattern': r'^(\d+\.)*\d+$' + }, + 'community': {'type': 'string'} + }, + 'required': [ + 'router', 'subscription', 'endpoint', 'oid', 'community'], + 'additionalProperties': False + }, + }, + + 'type': 'array', + 'items': {'$ref': '#/definitions/subscription'} +} + + @routes.after_request def after_request(resp): @@ -387,3 +421,78 @@ def interface_speeds(hostname=None): r.set(cache_key, result.encode('utf-8')) return Response(result, mimetype="application/json") + + +@routes.route("/eumetsat-multicast", methods=['GET', 'POST']) +@common.require_accepts_json +def eumetsat_multicast(hostname=None): + """ + Handler for `/poller/eumetsat-multicast` which returns information about + multicast subscriptions on mx1.fra.de.geant.net. + + The response is a list of oid/router/community structures that all + all subscription octet counters to be polled. + + .. asjson:: + inventory_provider.routes.poller.MULTICAST_SUBSCRIPTION_LIST_SCHEMA + + This method is basically hard-coded data, + based on the information in POL1-395. + + :return: + """ + + MX1_FRA = 'mx1.fra.de.geant.net' + SUBSCRIPTIONS = [{ + 'subscription': f'232.223.223.{idx}', + 'endpoint':'193.17.9.3', + } for idx in range(1, 73)] + + SUBSCRIPTIONS.append( + {'subscription': '232.223.223.1', 'endpoint': '193.17.9.7'}) + SUBSCRIPTIONS.append( + {'subscription': '232.223.223.22', 'endpoint': '193.17.9.7'}) + + def _oid(sub): + return ('1.3.6.1.2.1.83.1.1.2.1.16' + f'.{sub["subscription"]}.{sub["endpoint"]}' + '.255.255.255.255') + + + cache_key = f'classifier-cache:poller-eumetsat-multicast' + + r = common.get_current_redis() + + result = r.get(cache_key) + if result: + result = result.decode('utf-8') + else: + netconf = r.get(f'netconf:{MX1_FRA}') + if not netconf: + return Response( + status=503, + response=f'error loading netconf for {MX1_FRA}') + + netconf_doc = etree.fromstring(netconf.decode('utf-8')) + community = juniper.snmp_community_string(netconf_doc) + if not community: + return Response( + status=503, + response=f'error extracting community string for {MX1_FRA}') + + def _rsp_element(sub): + result = { + 'router': MX1_FRA, + 'oid': _oid(sub), + 'community': community + } + result.update(sub) + return result + + result = [_rsp_element(sub) for sub in SUBSCRIPTIONS] + + result = json.dumps(result) + # cache this data for the next call + r.set(cache_key, result.encode('utf-8')) + + return Response(result, mimetype="application/json") -- GitLab