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")