-
Robert Latta authoredRobert Latta authored
data.py 5.22 KiB
import json
import logging
import re
from flask import Blueprint, jsonify, Response, current_app, request
from inventory_provider.routes import common
from inventory_provider.routes.common import _ignore_cache_or_retrieve
logger = logging.getLogger(__name__)
routes = Blueprint("inventory-data-query-routes", __name__)
ROUTERS_RESPONSE_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {"type": "string"}
}
ROUTER_INTERFACES_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"router": {"type": "string"},
"bundle": {
"type": "array",
"items": {"type": "string"}
},
"ipv4": {
"type": "array",
"items": {"type": "string"}
},
"ipv6": {
"type": "array",
"items": {"type": "string"}
},
# only if not the default
"logical-system": {"type": "string"},
},
"required": ["name", "description", "ipv4", "router", "ipv6"],
"additionalProperties": False
}
}
POP_RESPONSE_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"pop-info": {
"type": "object",
"properties": {
"name": {"type": "string"},
"abbreviation": {"type": "string"},
"country": {"type": "string"},
"city": {"type": "string"},
"longitude": {"type": "number"},
"latitude": {"type": "number"}
},
"required": [
"name",
"abbreviation",
"country",
"city",
"longitude",
"latitude"
],
"additionalProperties": False
},
"equipment-info": {
"type": "object",
"properties": {
'equipment-name': {"type": "string"},
'status': {"type": "string"},
'pop': {"$ref": "#/definitions/pop-info"}
},
"required": [
"equipment-name",
"status",
"pop"
],
"additionalProperties": False
}
},
"type": "array",
"items": {"$ref": "#/definitions/equipment-info"}
}
@routes.after_request
def after_request(resp):
return common.after_request(resp)
@routes.route("/routers", methods=['GET', 'POST'])
@common.require_accepts_json
def routers():
"""
Handler for `/data/routers`.
The response will be a list of router hostnames
for which information is available and will formatted
according to the following schema:
.. asjson:: inventory_provider.routes.data.ROUTERS_RESPONSE_SCHEMA
:return:
"""
r = common.get_current_redis()
result = []
for k in r.keys('netconf:*'):
m = re.match('^netconf:(.+)$', k.decode('utf-8'))
assert m
result.append(m.group(1))
return jsonify(result)
@routes.route("/interfaces", methods=['GET', 'POST'])
@routes.route("/interfaces/<hostname>", methods=['GET', 'POST'])
@common.require_accepts_json
def router_interfaces(hostname=None):
"""
Handler for `/data/interfaces</hostname>`.
The response will be a list of information about
the interfaces present on the requested host
and will be formatted as follows:
.. asjson:: inventory_provider.routes.data.ROUTER_INTERFACES_SCHEMA
:param hostname: optional hostname
:return:
"""
cache_key = f'classifier-cache:netconf-interfaces:{hostname}' \
if hostname else 'classifier-cache:netconf-interfaces:all'
r = common.get_current_redis()
result = _ignore_cache_or_retrieve(request, cache_key, r)
if not result:
key_pattern = f'netconf-interfaces:{hostname}:*' \
if hostname else 'netconf-interfaces:*'
config = current_app.config['INVENTORY_PROVIDER_CONFIG']
result = []
for ifc in common.load_json_docs(config, key_pattern):
key_fields = ifc['key'].split(':')
ifc['value']['router'] = key_fields[1]
result.append(ifc['value'])
if not result:
return Response(
response="no available interface info for '%s'" % hostname,
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")
@routes.route("/pop/<equipment_name>", methods=['GET', 'POST'])
@common.require_accepts_json
@common.ims_hostname_decorator('equipment_name')
def equipment_location(equipment_name):
redis = common.get_current_redis()
result = redis.get(f'ims:location:{equipment_name}')
if not result:
return Response(
response="no available info for {}".format(equipment_name),
status=404,
mimetype="text/html")
return Response(result, mimetype="application/json")