Skip to content
Snippets Groups Projects
classifier.py 3.56 KiB
import functools

from flask import Blueprint, request, Response, current_app, jsonify
import json
import jsonschema

from inventory_provider import db

routes = Blueprint("inventory-data-classifier-support-routes", __name__)


def require_accepts_json(f):
    """
    used as a route handler decorator to return an error
    unless the request allows responses with type "application/json"
    :param f: the function to be decorated
    :return: the decorated function
    """
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        # TODO: use best_match to disallow */* ...?
        if not request.accept_mimetypes.accept_json:
            return Response(
                response="response will be json",
                status=406,
                mimetype="text/html")
        return f(*args, **kwargs)
    return decorated_function


@routes.route("/infinera-dna-addresses", methods=['GET', 'POST'])
@require_accepts_json
def infinera_addresses():
    infinera_config = current_app.config[
        "INVENTORY_PROVIDER_CONFIG"]["infinera-dna"]
    return jsonify([dna['address'] for dna in infinera_config])


@routes.route("/coriant-tnms-addresses", methods=['GET', 'POST'])
@require_accepts_json
def coriant_addresses():
    coriant_config = current_app.config[
        "INVENTORY_PROVIDER_CONFIG"]["coriant-tnms"]
    return jsonify([tnms['address'] for tnms in coriant_config])


@routes.route("/juniper-server-addresses", methods=['GET', 'POST'])
@require_accepts_json
def juniper_addresses():
    backend_data_schema = {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "ip_address": {"type": "string"}
            },
            "required": ["ip_address"]
        }
    }

    servers = db.get_redis().get('alarmsdb:juniper_servers')
    if not servers:
        return Response(
            response="no juniper server data found",
            status=404,
            mimetype="text/html")

    servers = json.loads(servers.decode('utf-8'))
    jsonschema.validate(servers, backend_data_schema)
    return jsonify([s['ip_address'] for s in servers])


@routes.route("/trap-metadata/<trap_type>/<source_equipment>/<path:interface>",
              methods=['GET', 'POST'])
@require_accepts_json
def get_trap_metadata(trap_type, source_equipment, interface):
    # todo - Move this to config
    interface_info_key = "interface_services"
    r = db.get_redis()

    # todo - Change this to a call to the yet-to-be-created one source of all
    #        relevant information
    # This could be different calls dependant on vendor, in which case we may
    # need to check the trap type, or it could be a case of a key check for
    # each possible data source
    interface_info = r.hget(interface_info_key,
                            "{}::{}".format(source_equipment, interface))

    if not interface_info:
        return Response(
            response="no available info for {} {}".format(
                source_equipment, interface),
            status=404,
            mimetype="text/html")

    interface_info = json.loads(interface_info.decode('utf-8'))

    # todo - refactor once structure of new source is decided, currently this
    #        is just a list of services
    vendor = interface_info[0]['manufacturer']
    hostname = interface_info[0]['equipment']
    result = {
        "vendor": vendor,
        "equipment-name": hostname,
        "interface-name": interface,
        "services": interface_info,
        "type": trap_type
    }

    return jsonify(result)