classifier.py 4.30 KiB
import ipaddress
import json
from flask import Blueprint, Response
from inventory_provider.routes import common
routes = Blueprint("inventory-data-classifier-support-routes", __name__)
@routes.route("/trap-metadata/<source_equipment>/<path:interface>",
methods=['GET', 'POST'])
@common.require_accepts_json
def get_trap_metadata(source_equipment, interface):
r = common.get_redis()
cache_key = 'classifier:cache:%s:%s' % (source_equipment, interface)
result = r.get(cache_key)
if result:
result = result.decode('utf-8')
else:
result = {}
services = r.get(
'opsdb:interface_services:%s:%s' % (source_equipment, interface))
if services:
result['services'] = json.loads(services.decode('utf=8'))
ifc_info = r.get(
'netconf-interfaces:%s:%s' % (source_equipment, interface))
if ifc_info:
result['interface'] = json.loads(ifc_info.decode('utf-8'))
if not result:
return Response(
response="no available info for {} {}".format(
source_equipment, interface),
status=404,
mimetype="text/html")
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")
def ix_peering_group(address, description):
"""
TODO: this is probably the least efficient way of doing this
(if it's a problem, pre-compute these lists)
:param ix_public_peer_info: ix public peer info loaded for address
:return:
"""
protocol = type(address).__name__
keyword = description.split(' ')[0] # regex needed??? (e.g. tabs???)
r = common.get_redis()
for k in r.keys('ix_public_peer:*'):
peer = r.get(k.decode('utf-8')).decode('utf-8')
peer = json.loads(peer)
assert peer['description'] is not None # sanity: as above...
if not peer['description'].startswith(keyword):
continue
peer_address = ipaddress.ip_address(peer['name'])
if protocol == type(peer_address).__name__:
yield peer['name']
def find_interfaces(address):
"""
TODO: this is probably the least efficient way of doing this
(if it's a problem, pre-compute these lists)
:param address: an ipaddress object
:return:
"""
r = common.get_redis()
for k in r.keys('reverse_interface_addresses:*'):
info = r.get(k.decode('utf-8')).decode('utf-8')
info = json.loads(info)
interface = ipaddress.ip_interface(info['interface address'])
if address in interface.network:
yield info
@routes.route("/peer-info/<address>", methods=['GET', 'POST'])
@common.require_accepts_json
def peer_info(address):
r = common.get_redis()
cache_key = 'classifier:peer-cache:%s' % address
result = r.get(cache_key)
if result:
result = result.decode('utf-8')
else:
try:
address_obj = ipaddress.ip_address(address)
except ValueError:
return Response(
response='unable to parse %r as an ip address' % address,
status=422,
mimetype="text/html")
result = {}
info = r.get('ix_public_peer:%s' % address)
if info:
info = info.decode('utf-8')
result['ix-public-peer-info'] = json.loads(info)
description = result['ix-public-peer-info']['description']
assert description is not None # sanity
result['ix-public-peer-group'] = list(
ix_peering_group(address_obj, description))
info = r.get('vpn_rr_peer:%s' % address)
if info:
info = info.decode('utf-8')
result['vpn-rr-peer-info'] = json.loads(info)
interfaces = list(find_interfaces(address_obj))
if interfaces:
result['interfaces'] = interfaces
if not result:
return Response(
response='no peering info found for %s' % address,
status=404,
mimetype="text/html")
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")