msr.py 4.75 KiB
import itertools
import json
from flask import Blueprint, jsonify, Response
from inventory_provider.routes import common
routes = Blueprint("msr-query-routes", __name__)
ACCESS_SERVICES_LIST_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"service": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"equipment": {"type": "string"},
"pop_name": {"type": "string"},
"other_end_equipment": {"type": "string"},
"other_end_pop_name": {"type": "string"},
"speed_value": {"type": "integer"},
"speed_unit": {"type": "string"}
},
"required": [
"id", "name",
"pop_name", "equipment",
"other_end_pop_name", "other_end_equipment",
"speed_value", "speed_unit"
],
"additionalProperties": False
}
},
"type": "array",
"items": {"$ref": "#/definitions/service"}
}
LOGICAL_SYSTEM_PEERING_LIST_SCHEMA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"peering-instance": {
"type": "object",
"properties": {
"address": {"type": "string"},
"description": {"type": "string"},
"logical-system": {"type": "string"},
"group": {"type": "string"},
"hostname": {"type": "string"},
"remote-asn": {"type": "integer"}
},
# only vrr peerings have remote-asn
"required": [
"address", "description", "logical-system", "group", "hostname"],
"additionalProperties": False
}
},
"type": "array",
"items": {"$ref": "#/definitions/peering-instance"}
}
@routes.after_request
def after_request(resp):
return common.after_request(resp)
@routes.route("/access-services", methods=['GET', 'POST'])
@common.require_accepts_json
def access_services():
"""
Handler for `/msr/access-services`.
This method is in development, not yet used.
The response will be formatted according to the following schema:
.. asjson::
inventory_provider.routes.msr.ACCESS_SERVICES_LIST_SCHEMA
:param name:
:return:
"""
redis = common.get_current_redis()
def _services():
for k in redis.scan_iter('opsdb:access_services:*'):
service = redis.get(k.decode('utf-8')).decode('utf-8')
yield json.loads(service)
cache_key = 'classifier-cache:msr:access-services'
result = redis.get(cache_key)
if result:
result = json.loads(result.decode('utf-8'))
else:
result = list(_services())
# cache this data for the next call
redis.set(cache_key, json.dumps(result).encode('utf-8'))
if not result:
return Response(
response='no access services found',
status=404,
mimetype="text/html")
return jsonify(result)
@routes.route("/logical-system-peerings", methods=['GET', 'POST'])
@routes.route("/logical-system-peerings/<name>", methods=['GET', 'POST'])
@common.require_accepts_json
def logical_system_peerings(name=None):
"""
Handler for `/msr/logical-system-peerings
This method will return a list of all peerings configured
for the requested logical-system name on any router, or for any
logical system if no parameter is given.
The response will be formatted according to the following schema:
.. asjson::
inventory_provider.routes.msr.LOGICAL_SYSTEM_PEERING_LIST_SCHEMA
:return:
"""
r = common.get_current_redis()
def _get_all_ls_keys():
keys = []
for k in r.scan_iter(f'juniper-peerings:logical-system:*', count=1000):
keys.append(k.decode('utf-8'))
return keys
def _load_list_items(key):
value = r.get(key)
if value:
yield from json.loads(value.decode('utf-8'))
cache_key = 'classifier-cache:msr:logical-system-peerings'
if name:
cache_key = f'{cache_key}:name'
items = r.get(cache_key)
if items:
items = json.loads(items.decode('utf-8'))
else:
if name:
items = _load_list_items(f'juniper-peerings:logical-system:{name}')
else:
gen_list = list(map(_load_list_items, _get_all_ls_keys()))
items = itertools.chain(*gen_list)
items = list(items)
if not items:
return Response(
response='no peerings found',
status=404,
mimetype="text/html")
r.set(cache_key, json.dumps(items).encode('utf-8'))
return jsonify(items)