Skip to content
Snippets Groups Projects
poller.py 3.42 KiB
import json

from flask import Blueprint, Response, jsonify
from lxml import etree
from inventory_provider import juniper
from inventory_provider.routes import common

routes = Blueprint('poller-support-routes', __name__)


@routes.after_request
def after_request(resp):
    return common.after_request(resp)


@routes.route('/interfaces/<hostname>', methods=['GET', 'POST'])
@common.require_accepts_json
def poller_interface_oids(hostname):
    r = common.get_current_redis()

    netconf_string = r.get('netconf:' + hostname)
    if not netconf_string:
        return Response(
            response='no netconf available info for %r' % hostname,
            status=404,
            mimetype='text/html')

    snmp_data_string = r.get('snmp-interfaces:' + hostname)
    if not snmp_data_string:
        return Response(
            response='no snmp available info for %r' % hostname,
            status=404,
            mimetype='text/html')

    snmp_indexes = {}
    for ifc in json.loads(snmp_data_string.decode('utf-8')):
        snmp_indexes[ifc['name']] = ifc['index']

    interfaces = list(juniper.list_interfaces(
        etree.XML(netconf_string.decode('utf-8'))))

    if not interfaces:
        return Response(
            response='no interfaces found for %r' % hostname,
            status=404,
            mimetype='text/html')

    result = []
    for ifc in interfaces:
        if not ifc['description']:
            continue

        snmp_index = snmp_indexes.get(ifc['name'], None)
        if not snmp_index:
            continue

        bundle_parents = r.get('netconf-interface-bundles:%s:%s' % (
            hostname, ifc['name'].split('.')[0]))

        ifc_data = {
            'name': ifc['name'],
            'bundle': ifc['bundle'],
            'bundle-parents':
                json.loads(bundle_parents) if bundle_parents else [],
            'snmp-index': snmp_index,
            'description': ifc['description'],
            'circuits': []
        }

        circuits = r.get(
            'opsdb:interface_services:%s:%s' % (hostname, ifc['name']))
        if circuits:
            ifc_data['circuits'] = [
                {
                    'id': c['id'],
                    'name': c['name'],
                    'type': c['service_type'],
                    'status': c['status']
                } for c in json.loads(circuits.decode('utf-8'))
            ]

        result.append(ifc_data)

    return jsonify(result)


@routes.route('/services/<category>', methods=['GET', 'POST'])
@common.require_accepts_json
def service_category_interfaces(category):

    def _interfaces():
        r = common.get_current_redis()
        for k in r.scan_iter(f'interface-services:{category.lower()}:*'):
            cached_ifc = r.get(k.decode('utf-8')).decode('utf-8')
            cached_ifc = json.loads(cached_ifc)
            basic_ifc_info = dict()
            for k in ['description', 'interface', 'router']:
                basic_ifc_info[k] = cached_ifc[k]
            if not cached_ifc['users']:
                yield basic_ifc_info
            else:
                for user in cached_ifc['users']:
                    ifc = {'user': user}
                    ifc.update(basic_ifc_info)
                    yield ifc

    result = list(_interfaces())

    if not result:
        return Response(
            response=f'no info available for service category {category}',
            status=404,
            mimetype="text/html")

    return jsonify(result)