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

Finished feature coriant-info.

parents a910e575 adb6c6d3
No related branches found
No related tags found
No related merge requests found
...@@ -242,3 +242,127 @@ def get_equipment_location_data(connection): # pragma: no cover ...@@ -242,3 +242,127 @@ def get_equipment_location_data(connection): # pragma: no cover
crs.execute(equipment_location_query) crs.execute(equipment_location_query)
r = _convert_to_dict(crs) r = _convert_to_dict(crs)
return r return r
def get_coriant_path(connection, equipment_name, card_id, port_number):
base_query = """
SELECT
vcc.absid,
vcc.category,
vcc.circuit_type,
vcc.service_type,
vcc.peering_type,
eq_a.name as equipment_name_a,
eq_b.name as equipment_name_b,
eqc_a.card_id as card_id_a,
eqc_a.card_id as card_id_b,
pop_a.name as pop_name_a,
pop_b.name as pop_name_b,
vcc.port_a as port_a,
vcc.port_b as port_b
FROM vcircuitconns vcc
LEFT JOIN equipment eq_a ON eq_a.absid = vcc.PTR_equip_a
LEFT JOIN equipment eq_b ON eq_b.absid = vcc.PTR_equip_b
LEFT JOIN equipment_card eqc_a ON eqc_a.absid = vcc.PTR_card_a
LEFT JOIN equipment_card eqc_b ON eqc_b.absid = vcc.PTR_card_b
LEFT JOIN pop pop_a ON pop_a.absid = vcc.PTR_pop_a
LEFT JOIN pop pop_b ON pop_b.absid = vcc.PTR_pop_b
"""
def _fields2rsp(row):
return {
'absid': row['absid'],
'category': row['category'],
'circuit_type': row['circuit_type'],
'service_type': row['service_type'],
'peering_type': row['peering_type'],
'a': {
'name': row['equipment_name_a'],
'card id': row['card_id_a'],
'port number': row['port_a'],
'pop': row['pop_name_a']
},
'b': {
'name': row['equipment_name_b'],
'card id': row['card_id_b'],
'port number': row['port_b'],
'pop': row['pop_name_b']
}
}
circuit_query = base_query + """
WHERE vcc.status = 'Operational'
AND (
(eq_a.name = %(equipment_name)s
AND eqc_a.card_id = %(card_id)s
AND vcc.port_a = %(port_number)s )
OR
(eq_b.name = %(equipment_name)s
AND eqc_b.card_id = %(card_id)s
AND vcc.port_b = %(port_number)s ))
ORDER BY FIELD(vcc.circuit_type, 'path') DESC
"""
parent_query = base_query + """
JOIN circuit_glue
ON circuit_glue.PTR_circuit = vcc.absid
WHERE circuit_glue.PTR_component = %s
AND circuit_type = 'Path'
"""
# for_testing = """
# SELECT parent.absid, child.absid,
# parent.circuit_type as parent_circuit_type,
# child.circuit_type as child_circuit_type,
# eq_a.name as equipment_name_a,
# eq_b.name as equipment_name_b,
# eqc_a.card_id as card_id_a,
# eqc_a.card_id as card_id_b,
# pop_a.name as pop_name_a,
# pop_b.name as pop_name_b,
# parent.port_a as port_a,
# parent.port_b as port_b,
# child.port_a as child_port_a,
# child.port_b as child_port_b
#
# FROM vcircuitconns parent
# RIGHT JOIN circuit_glue
# ON circuit_glue.PTR_circuit = parent.absid
# JOIN vcircuitconns child
# ON circuit_glue.PTR_component = child.absid
#
# LEFT JOIN equipment eq_a ON eq_a.absid = parent.PTR_equip_a
# LEFT JOIN equipment eq_b ON eq_b.absid = parent.PTR_equip_b
# LEFT JOIN equipment_card eqc_a ON eqc_a.absid = parent.PTR_card_a
# LEFT JOIN equipment_card eqc_b ON eqc_b.absid = parent.PTR_card_b
# LEFT JOIN pop pop_a ON pop_a.absid = parent.PTR_pop_a
# LEFT JOIN pop pop_b ON pop_b.absid = parent.PTR_pop_b
#
# WHERE parent.circuit_type = 'Path'
# AND child.circuit_type <> 'Path'
# AND child.status = 'Operational'
# AND (eq_a.name like 'grv%' or eq_b.name like 'grv%')
# """
args = {
'equipment_name': equipment_name,
'card_id': card_id,
'port_number': port_number
}
with db.cursor(connection) as crs:
crs.execute(circuit_query, args)
r = _convert_to_dict(crs)
if not r:
return None
circuit = r[0]
if circuit['circuit_type'].lower() == 'path':
return _fields2rsp(circuit)
crs.execute(parent_query, [circuit['absid']])
r = _convert_to_dict(crs)
return _fields2rsp(r[0]) if r else None
...@@ -2,9 +2,10 @@ import ipaddress ...@@ -2,9 +2,10 @@ import ipaddress
import json import json
import re import re
from flask import Blueprint, Response from flask import Blueprint, Response, current_app
from inventory_provider.routes import common from inventory_provider.routes import common
from inventory_provider.db import opsdb, db
routes = Blueprint("inventory-data-classifier-support-routes", __name__) routes = Blueprint("inventory-data-classifier-support-routes", __name__)
...@@ -277,3 +278,36 @@ def get_trap_metadata(source_equipment, interface, circuit_id): ...@@ -277,3 +278,36 @@ def get_trap_metadata(source_equipment, interface, circuit_id):
r.set(cache_key, result.encode('utf-8')) r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype="application/json") return Response(result, mimetype="application/json")
@routes.route("/coriant-info/"
"<equipment_name>/<card_id>/<port_number>",
methods=['GET', 'POST'])
@common.require_accepts_json
def get_coriant_info(equipment_name, card_id, port_number):
r = common.get_redis()
cache_key = 'classifier-cache:coriant:%s:%s:%s' % (
equipment_name, card_id, port_number)
result = r.get(cache_key)
if result:
result = result.decode('utf-8')
else:
config = current_app.config['INVENTORY_PROVIDER_CONFIG']
with db.connection(config['ops-db']) as cx:
path = opsdb.get_coriant_path(
cx, equipment_name, card_id, port_number)
if not path:
return Response(
response="no available info for {} {} {}".format(
equipment_name, card_id, port_number),
status=404,
mimetype="text/html")
result = json.dumps({'path': path})
# cache this data for the next call
r.set(cache_key, result.encode('utf-8'))
return Response(result, mimetype="application/json")
import contextlib
import json import json
import jsonschema import jsonschema
import pytest import pytest
...@@ -271,3 +272,58 @@ def test_peer_not_found(client_with_mocked_data): ...@@ -271,3 +272,58 @@ def test_peer_not_found(client_with_mocked_data):
'/classifier/peer-info/1.2.3.4', '/classifier/peer-info/1.2.3.4',
headers=DEFAULT_REQUEST_HEADERS) headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 404 assert rv.status_code == 404
def test_coriant_info(client, mocker):
"""
just check the correct method is called, but mock out all sql access
"""
expected_path = {
'C': 'bogus connection',
'E': 'bogus equipment name',
'CID': 'bogus card id',
'P': 'bogus card number'
}
@contextlib.contextmanager
def mocked_connection(ignored):
yield expected_path['C']
mocker.patch(
'inventory_provider.db.db.connection', mocked_connection)
mocker.patch(
'inventory_provider.db.opsdb.get_coriant_path',
lambda a, b, c, d: {'C': a, 'E': b, 'CID': c, 'P': d})
rv = client.get(
'/classifier/coriant-info/{E}/{CID}/{P}'.format(**expected_path),
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 200
assert rv.is_json
response_data = json.loads(rv.data.decode('utf-8'))
expected_response = {'path': expected_path}
assert response_data == expected_response
def test_coriant_info_not_found(client, mocker):
"""
just check the correct method is called, but mock out all sql access
"""
@contextlib.contextmanager
def mocked_connection(ignored):
yield None
mocker.patch(
'inventory_provider.db.db.connection', mocked_connection)
mocker.patch(
'inventory_provider.db.opsdb.get_coriant_path',
lambda a, b, c, d: None)
rv = client.get(
'/classifier/coriant-info/aaa/bbb/ccc',
headers=DEFAULT_REQUEST_HEADERS)
assert rv.status_code == 404
import os
import pytest
from inventory_provider.db import db
from inventory_provider.db import opsdb
pytestmark = pytest.mark.skipif(
'TEST_OPSDB_HOSTNAME' not in os.environ,
reason='TEST_OPSDB_HOSTNAME environment variable not found')
pytestmark = pytest.mark.skipif(
'TEST_OPSDB_DBNAME' not in os.environ,
reason='TEST_OPSDB_DBNAME environment variable not found')
pytestmark = pytest.mark.skipif(
'TEST_OPSDB_USERNAME' not in os.environ,
reason='TEST_OPSDB_USERNAME environment variable not found')
pytestmark = pytest.mark.skipif(
'TEST_OPSDB_PASSWORD' not in os.environ,
reason='TEST_OPSDB_PASSWORD environment variable not found')
@pytest.fixture
def db_params():
return {
'hostname': os.environ['TEST_OPSDB_HOSTNAME'],
'dbname': os.environ['TEST_OPSDB_DBNAME'],
'username': os.environ['TEST_OPSDB_USERNAME'],
'password': os.environ['TEST_OPSDB_PASSWORD'],
}
@pytest.fixture
def connection(db_params):
with db.connection(db_params) as c:
yield c
@pytest.mark.parametrize('equipment,card,port', [
('grv3.lon.uk.geant.net', '1-1', '3'),
('grv3.lon.uk.geant.net', '1-1', '5'),
('grv1.ams.nl.geant.net', '1-1', '1'),
('grv3.lon.uk.geant.net', '1-1', '1'),
])
def test_query(connection, equipment, card, port):
circuit = opsdb.get_coriant_path(connection, equipment, card, port)
from pprint import pprint
pprint(circuit)
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
envlist = py36 envlist = py36
[testenv] [testenv]
passenv = TEST_OPSDB_HOSTNAME TEST_OPSDB_DBNAME TEST_OPSDB_USERNAME TEST_OPSDB_PASSWORD
deps = deps =
coverage coverage
flake8 flake8
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment