-
Robert Latta authoredRobert Latta authored
data.py 5.94 KiB
import functools
import json
import pkg_resources
from flask import Blueprint, jsonify, request, Response, current_app
from lxml import etree
import redis
from inventory_provider import db, juniper
routes = Blueprint("inventory-data-query-routes", __name__)
API_VERSION = '0.1'
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("/version", methods=['GET', 'POST'])
@require_accepts_json
def version():
return Response(
json.dumps({
'api': API_VERSION,
'module':
pkg_resources.get_distribution('inventory_provider').version
}),
mimetype="application/json"
)
@routes.route("/routers", methods=['GET', 'POST'])
@require_accepts_json
def routers():
redis_config = current_app.config["INVENTORY_PROVIDER_CONFIG"]["redis"]
r = redis.StrictRedis(
host=redis_config["hostname"],
port=redis_config["port"])
return Response(
json.dumps(list([k.decode("utf-8") for k in r.keys("*")])),
mimetype="application/json")
@routes.route("/interfaces/<hostname>", methods=['GET', 'POST'])
@require_accepts_json
def router_interfaces(hostname):
redis_config = current_app.config["INVENTORY_PROVIDER_CONFIG"]["redis"]
r = redis.StrictRedis(
host=redis_config["hostname"],
port=redis_config["port"])
netconf_string = r.hget(hostname, 'netconf')
if not netconf_string:
return Response(
response="no available info for '%s'" % hostname,
status=404,
mimetype="text/html")
interfaces = list(juniper.list_interfaces(
etree.XML(netconf_string.decode('utf-8'))))
if not interfaces:
return Response(
response="no interfaces found for '%s'" % hostname,
status=404,
mimetype="text/html")
return Response(
json.dumps(interfaces),
mimetype="application/json")
@routes.route("/snmp/<hostname>", methods=['GET', 'POST'])
@require_accepts_json
def snmp_ids(hostname):
redis_config = current_app.config["INVENTORY_PROVIDER_CONFIG"]["redis"]
r = redis.StrictRedis(
host=redis_config["hostname"],
port=redis_config["port"])
ifc_data_string = r.hget(hostname, 'snmp-interfaces')
if not ifc_data_string:
return Response(
response="no available info for '%s'" % hostname,
status=404,
mimetype="text/html")
def _ifc_name(ifc):
if 'v4InterfaceName' in ifc:
return ifc['v4InterfaceName']
if 'v6InterfaceName' in ifc:
return ifc['v6InterfaceName']
assert False, "sanity failure: no interface name found"
ifc_data = json.loads(ifc_data_string.decode('utf-8'))
result = [
{'index': i['index'], 'name': _ifc_name(i)}
for i in ifc_data]
return Response(
json.dumps(result),
mimetype="application/json")
@routes.route("/debug-dump/<hostname>", methods=['GET', 'POST'])
@require_accepts_json
def debug_dump_router_info(hostname):
redis_config = current_app.config["INVENTORY_PROVIDER_CONFIG"]["redis"]
r = redis.StrictRedis(
host=redis_config["hostname"],
port=redis_config["port"])
info = dict([(k.decode('utf-8'), json.loads(v.decode('utf-8')))
for k, v in r.hgetall(hostname).items()])
if not info:
return Response(
response="no info found for router '%s'" % hostname,
status=404,
mimetype="text/html")
return Response(
json.dumps(info),
mimetype="application/json")
@routes.route("/bgp/<hostname>", methods=['GET', 'POST'])
@require_accepts_json
def bgp_configs(hostname):
redis_config = current_app.config["INVENTORY_PROVIDER_CONFIG"]["redis"]
r = redis.StrictRedis(
host=redis_config["hostname"],
port=redis_config["port"])
netconf_string = r.hget(hostname, 'netconf')
if not netconf_string:
return Response(
response="no available info for '%s'" % hostname,
status=404,
mimetype="text/html")
routes = list(juniper.list_bgp_routes(
etree.XML(netconf_string.decode('utf-8'))))
if not routes:
return Response(
response="no interfaces found for '%s'" % hostname,
status=404,
mimetype="text/html")
return Response(
json.dumps(routes),
mimetype="application/json")
@routes.route("/interfaces/status/<hostname>/<path:interface>",
methods=['GET', 'POST'])
@require_accepts_json
def interface_statuses(hostname, interface):
r = db.get_redis()
result = r.hget("interface_statuses",
"{}::{}".format(hostname, interface))
if not result:
return Response(
response="no available info for {} {}".format(hostname, interface),
status=404,
mimetype="text/html")
return jsonify({"status": result.decode('utf-8')})
@routes.route("/services/<hostname>/<path:interface>",
methods=['GET', 'POST'])
def services_for_interface(hostname, interface):
r = db.get_redis()
result = r.hget("interface_services",
"{}::{}".format(hostname, interface))
if not result:
return Response(
response="no available info for {} {}".format(hostname, interface),
status=404,
mimetype="text/html")
return jsonify(json.loads(result.decode('utf-8')))