Skip to content
Snippets Groups Projects
Commit 4703249d authored by Erik Reid's avatar Erik Reid
Browse files

Finished feature add-related-interface-services-to-metadata.

parents 82aaa8c2 04211843
No related branches found
No related tags found
No related merge requests found
import ipaddress
import json
import re
from flask import Blueprint, Response
......@@ -33,6 +34,22 @@ def handle_request_error(error):
status=error.status_code)
def base_interface_name(interface):
m = re.match(r'(.*?)(\.\d+)?$', interface)
assert m # sanity: anything should match
return m.group(1)
def related_interfaces(hostname, interface):
r = common.get_redis()
prefix = 'netconf-interfaces:%s:' % hostname
for k in r.keys(prefix + base_interface_name(interface) + '*'):
k = k.decode('utf-8')
assert k.startswith(prefix) # sanity
assert len(k) > len(prefix) # sanity (contains at least an interface)
yield k[len(prefix):]
@routes.route("/trap-metadata/<source_equipment>/<path:interface>",
methods=['GET', 'POST'])
@common.require_accepts_json
......@@ -57,6 +74,18 @@ def get_trap_metadata(source_equipment, interface):
if ifc_info:
result['interface'] = json.loads(ifc_info.decode('utf-8'))
def _related_services():
for related in related_interfaces(source_equipment, interface):
rs = r.get('opsdb:interface_services:%s:%s'
% (source_equipment, related))
if rs:
for s in json.loads(rs.decode('utf-8')):
yield s
related_services = list(_related_services())
if related_services:
result['related-services'] = related_services
if not result:
return Response(
response="no available info for {} {}".format(
......
......@@ -7,19 +7,123 @@ DEFAULT_REQUEST_HEADERS = {
"Accept": ["application/json"]
}
JUNIPER_LINK_METADATA = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"ip-address": {
"type": "string",
"oneOf": [
{"pattern": r'^(\d+\.){3}\d+$'},
{"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'}
]
},
"ipv4-interface-address": {
"type": "string",
"pattern": r'^(\d+\.){3}\d+/\d+$'
},
"ipv6-interface-address": {
"type": "string",
"pattern": r'^[a-f\d:]+/\d+$'
},
"interface-info": {
"type": "object",
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"ipv4": {
"type": "array",
"items": {"$ref": "#/definitions/ipv4-interface-address"}
},
"ipv6": {
"type": "array",
"items": {"$ref": "#/definitions/ipv6-interface-address"}
}
},
"required": ["name", "description", "ipv4", "ipv6"],
"additionalProperties": False
},
"service-info": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"},
"status": {
"type": "string",
"enum": ["operational", "installed", "planned", "ordered"]
},
"circuit_type": {
"type": "string",
"enum": ["path", "service", "l2circuit"]
},
"service_type": {"type": "string"},
"project": {"type": "string"},
"equipment": {"type": "string"},
"other_end_equipment": {"type": "string"},
"port": {"type": "string"},
"logical_unit": {
"oneOf": [
{"type": "integer"},
{"type": "string", "maxLength": 0}
]
},
"other_end_logical_unit": {
"oneOf": [
{"type": "integer"},
{"type": "string", "maxLength": 0}
]
},
"manufacturer": {
"type": "string",
"enum": ["juniper", "coriant", "infinera",
"cisco", "hewlett packard",
"corsa", "graham smith uk ltd",
"unknown", ""]
},
"card_id": {"type": "string"},
"other_end_card_id": {"type": "string"},
"interface_name": {"type": "string"},
"other_end_interface_name": {"type": "string"}
},
# TODO: modify service-info so that "" entries are just omitted
# (... rather than requiring 'oneOf')
# TODO: put 'other_end_*' params in a sub dictionary
"required": [
"id", "name", "status",
"circuit_type", "service_type",
"project", "port", "manufacturer",
"equipment", "logical_unit", "card_id", "interface_name"
],
"additionalProperties": False
}
},
"type": "object",
"properties": {
"services": {
"type": "array",
"items": {"$ref": "#/definitions/service-info"}
},
"interface": {"$ref": "#/definitions/interface-info"},
"related-services": {
"type": "array",
"items": {"$ref": "#/definitions/service-info"}
}
},
"required": ["interface"],
"additionalProperties": False
}
def test_trap_metadata(client_with_mocked_data):
response_schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object"
}
rv = client_with_mocked_data.get(
'/classifier/trap-metadata/mx1.ams.nl.geant.net/ae15.1500',
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
jsonschema.validate(response_data, response_schema)
jsonschema.validate(response_data, JUNIPER_LINK_METADATA)
VPN_RR_PEER_INFO_KEYS = {'vpn-rr-peer-info'}
......
import pytest
from inventory_provider.routes import classifier
@pytest.mark.parametrize('interface_name,base_name', [
('ae0', 'ae0'),
('ae0.0', 'ae0'),
('ae1.0', 'ae1'),
('ae10.2603', 'ae10'),
('et-3/1/2', 'et-3/1/2'),
('et-3/1/2.100', 'et-3/1/2'),
('xe-2/1/0', 'xe-2/1/0'),
('xe-2/1/0.933', 'xe-2/1/0'),
# degenerate cases ... check expected regex behavior
('xe-2/1/0.933.933', 'xe-2/1/0.933'),
(' sss.333.aaa ', ' sss.333.aaa '),
(' sss.333.aaa .999', ' sss.333.aaa ')
]
)
def test_base_interface_name(interface_name, base_name):
assert classifier.base_interface_name(interface_name) == base_name
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment