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('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)