Skip to content
Snippets Groups Projects
Commit c43d7fa7 authored by Erik Reid's avatar Erik Reid
Browse files

Finished feature POL1-395-poller-multicast-info.

parents 8ea55da6 2517b0ea
No related branches found
No related tags found
No related merge requests found
...@@ -18,3 +18,9 @@ These endpoints are intended for use by BRIAN. ...@@ -18,3 +18,9 @@ These endpoints are intended for use by BRIAN.
--------------------------------- ---------------------------------
.. autofunction:: inventory_provider.routes.poller.interface_speeds .. autofunction:: inventory_provider.routes.poller.interface_speeds
/poller/eumetsat-multicast
---------------------------------
.. autofunction:: inventory_provider.routes.poller.eumetsat_multicast
...@@ -3,6 +3,8 @@ import logging ...@@ -3,6 +3,8 @@ import logging
import re import re
from flask import Blueprint, Response, current_app from flask import Blueprint, Response, current_app
from lxml import etree
from inventory_provider import juniper from inventory_provider import juniper
from inventory_provider.routes import common from inventory_provider.routes import common
...@@ -61,6 +63,7 @@ INTERFACE_LIST_SCHEMA = { ...@@ -61,6 +63,7 @@ INTERFACE_LIST_SCHEMA = {
'items': {'$ref': '#/definitions/interface'} 'items': {'$ref': '#/definitions/interface'}
} }
INTERFACE_SPEED_LIST_SCHEMA = { INTERFACE_SPEED_LIST_SCHEMA = {
'$schema': 'http://json-schema.org/draft-07/schema#', '$schema': 'http://json-schema.org/draft-07/schema#',
...@@ -81,6 +84,36 @@ INTERFACE_SPEED_LIST_SCHEMA = { ...@@ -81,6 +84,36 @@ INTERFACE_SPEED_LIST_SCHEMA = {
'items': {'$ref': '#/definitions/interface'} '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 @routes.after_request
def after_request(resp): def after_request(resp):
...@@ -387,3 +420,77 @@ def interface_speeds(hostname=None): ...@@ -387,3 +420,77 @@ def interface_speeds(hostname=None):
r.set(cache_key, result.encode('utf-8')) r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype="application/json") 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 returns essentially 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 = '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")
import json import json
import jsonschema import jsonschema
from inventory_provider.routes.poller import INTERFACE_LIST_SCHEMA from inventory_provider.routes import poller
DEFAULT_REQUEST_HEADERS = { DEFAULT_REQUEST_HEADERS = {
"Content-type": "application/json", "Content-type": "application/json",
...@@ -15,7 +15,38 @@ def test_get_all_interfaces(client): ...@@ -15,7 +15,38 @@ def test_get_all_interfaces(client):
assert rv.status_code == 200 assert rv.status_code == 200
assert rv.is_json assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8')) response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, INTERFACE_LIST_SCHEMA) jsonschema.validate(response_data, poller.INTERFACE_LIST_SCHEMA)
response_routers = {ifc['router'] for ifc in response_data} response_routers = {ifc['router'] for ifc in response_data}
assert len(response_routers) > 1, \ assert len(response_routers) > 1, \
'there should data from be lots of routers' 'there should data from be lots of routers'
def test_all_router_interface_speeds(client):
rv = client.post(
'/poller/speeds',
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
response = json.loads(rv.data.decode("utf-8"))
jsonschema.validate(response, poller.INTERFACE_SPEED_LIST_SCHEMA)
assert response # at least shouldn't be empty
response_routers = {ifc['router'] for ifc in response}
assert len(response_routers) > 1, \
'there should data from be lots of routers'
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'
rv = client.get(
'/poller/eumetsat-multicast',
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(
response_data, poller.MULTICAST_SUBSCRIPTION_LIST_SCHEMA)
assert response_data, "the subscription list shouldn't be empty"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment