diff --git a/docs/source/protocol/classifier.rst b/docs/source/protocol/classifier.rst index f57083f1513263144a2c67f5efd834fbf75b3b90..3b2b348c02d0bf45f3fb529732835e2a25184844 100644 --- a/docs/source/protocol/classifier.rst +++ b/docs/source/protocol/classifier.rst @@ -4,8 +4,30 @@ Classifier Endpoints ========================= +/classifier/peer-info +--------------------- -.. autofunction:: inventory_provider.routes.classifier.peer_info +.. autofunction:: inventory_provider.routes.classifier.get_bgp_peer_info + +/classifier/juniper-link-info +----------------------------- .. autofunction:: inventory_provider.routes.classifier.get_juniper_link_info + +/classifier/infinera-lambda-info +-------------------------------- + +.. autofunction:: inventory_provider.routes.classifier.get_infinera_lambda_info + + +/classifier/infinera-fiberlink-info +------------------------------------ + +.. autofunction:: + inventory_provider.routes.classifier.get_fiberlink_trap_metadata + +/classifier/coriant-info +------------------------ + +.. autofunction:: inventory_provider.routes.classifier.get_coriant_info \ No newline at end of file diff --git a/docs/source/protocol/index.rst b/docs/source/protocol/index.rst index 93a5664c91e361d5de1b463eb8877aa22c491b95..c2286ca15b5d8db8e08526a1ad38c53b9e8ca821 100644 --- a/docs/source/protocol/index.rst +++ b/docs/source/protocol/index.rst @@ -22,7 +22,7 @@ and www.json.org for more details. classifier -Version +/version ------------- .. autofunction:: inventory_provider.routes.default.version diff --git a/inventory_provider/routes/classifier.py b/inventory_provider/routes/classifier.py index 877ae86348670cb80076356911c78311b9e61310..f1bb72de10ed59d583d59be31d8ff2268b3ad1c7 100644 --- a/inventory_provider/routes/classifier.py +++ b/inventory_provider/routes/classifier.py @@ -486,7 +486,7 @@ def find_interfaces_and_services(address_str): @routes.route("/peer-info/<address>", methods=['GET', 'POST']) @common.require_accepts_json -def peer_info(address): +def get_bgp_peer_info(address): """ Handler for /classifier/peer-info that returns bgp peering metadata. @@ -565,7 +565,21 @@ def peer_info(address): "<source_equipment>/<interface>/<circuit_id>", methods=['GET', 'POST']) @common.require_accepts_json -def get_trap_metadata(source_equipment, interface, circuit_id): +def get_infinera_lambda_info(source_equipment, interface, circuit_id): + """ + Handler for /classifier/infinera-lambda-info that + returns metadata for as DTNX port. + + The response will be formatted according to the following schema: + + .. asjson:: + inventory_provider.routes.classifier_schema.INFINERA_LAMBDA_INFO_RESPONSE_SCHEMA + + :param source_equipment: DTNX name + :param address: interface/port name + :param circuit_id: infinera circuit id + :return: + """ interface = interface.replace('-T', '-') cache_key = 'classifier-cache:infinera:%s:%s' % ( @@ -619,6 +633,17 @@ def get_trap_metadata(source_equipment, interface, circuit_id): methods=['GET', 'POST']) @common.require_accepts_json def get_fiberlink_trap_metadata(ne_name_str, object_name_str): + """ + Handler for /classifier/infinera-fiberlink-info that + returns metadata for a particular opitical path segment. + + TODO: no schema is declared, and there are no validation tests + + :param ne_name_str: OLA or DTNX equipment name + :param object_name_str: path name + :return: + """ + objects = object_name_str.split('_') shelves = [x.split('-')[0] for x in objects] p = r'([a-zA-Z\d]+?-(OLA|DTNX)\d+(-\d)?)' @@ -689,6 +714,20 @@ def get_fiberlink_trap_metadata(ne_name_str, object_name_str): methods=['GET', 'POST']) @common.require_accepts_json def get_coriant_info(equipment_name, entity_string): + """ + Handler for /classifier/coriant-info that + returns metadata for a coriant path. + + The response will be formatted according to the following schema: + + .. asjson:: + inventory_provider.routes.classifier_schema.CORIANT_INFO_RESPONSE_SCHEMA + + :param source_equipment: grv hostname + :param entity_string: path name + :return: + """ + r = common.get_current_redis() cache_key = 'classifier-cache:coriant:%s:%s' % ( diff --git a/inventory_provider/routes/classifier_schema.py b/inventory_provider/routes/classifier_schema.py index 8d132b14a5b011eade02e47f083258ccdb5a06f6..3d2ca9e1fd986318e751fc95bbe69629f7700059 100644 --- a/inventory_provider/routes/classifier_schema.py +++ b/inventory_provider/routes/classifier_schema.py @@ -1,4 +1,5 @@ + _common_locations_schema_definitions = { "location-endpoint": { "type": "object", @@ -328,3 +329,226 @@ PEER_INFO_RESPONSE_SCHEMA = { }, "additionalProperties": False } + +_infinera_lambda_response_schema_definitions = { + "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"}, + "pop_name": {"type": "string"}, + "pop_abbreviation": {"type": "string"}, + "other_end_pop_name": {"type": "string"}, + "other_end_pop_abbreviation": {"type": "string"}, + "equipment": {"type": "string"}, + "other_end_equipment": {"type": "string"}, + "port": {"type": "string"}, + "other_end_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"} + }, + "additionalProperties": False + }, + "related-service-info": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "status": { + "type": "string", + "enum": ["operational", "installed", "planned", "ordered"] + }, + "circuit_type": { + "type": "string", + "enum": ["path", "service", "l2circuit"] + }, + "project": {"type": "string"} + }, + "required": ["name", "status", "circuit_type", "project"], + "additionalProperties": False + }, + "geant-lambda": { + "type": "object", + "properties": { + "id": {"type": "integer"}, + "name": {"type": "string"}, + "project": {"type": "string"}, + "status": { + "type": "string", + "enum": ["operational", "installed", "planned", "ordered"] + }, + }, + "additionalProperties": False + } +} + +INFINERA_LAMBDA_INFO_RESPONSE_SCHEMA = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + + "definitions": { + **_infinera_lambda_response_schema_definitions, + **_common_locations_schema_definitions + }, + + "type": "object", + "properties": { + "services": { + "type": "array", + "items": {"$ref": "#/definitions/service-info"} + }, + "related-services": { + "type": "array", + "items": {"$ref": "#/definitions/related-service-info"} + }, + "geant-lambda": { + "$ref": "#/definitions/geant-lambda" + }, + "locations": {"$ref": "#/definitions/locations-list"} + }, + "additionalProperties": False +} + +CORIANT_INFO_RESPONSE_SCHEMA = { + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + + "definitions": { + "location-endpoint": { + "type": "object", + "properties": { + "equipment": {"type": "string"}, + "name": {"type": "string"}, + "abbreviation": {"type": "string"} + }, + "required": ["equipment", "name", "abbreviation"], + "additionalProperties": False + }, + "location": { + "type": "object", + "properties": { + "a": {"$ref": "#/definitions/location-endpoint"}, + "b": {"$ref": "#/definitions/location-endpoint"} + }, + "required": ["a"], + "additionalProperties": False + }, + "locations-list": { + "type": "array", + "items": {"$ref": "#/definitions/location"} + }, + "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 + }, + "endpoint": { + "type": "object", + "properties": { + "equipment name": {"type": "string"}, + "card id": {"type": "string"}, + "port number": {"type": "string"}, + "pop": {"$ref": "#/definitions/pop-info"} + }, + "required": ["equipment name", "port number", "pop"], + "additionalProperties": False + }, + "path": { + "type": "object", + "properties": { + 'category': {"type": "string"}, + 'circuit_type': {"type": "string"}, + 'service_type': {"type": "string"}, + 'peering_type': {"type": "string"}, + 'status': {"type": "string"}, + 'name': {"type": "string"}, + 'a': {"$ref": "#/definitions/endpoint"}, + 'b': {"$ref": "#/definitions/endpoint"} + }, + "required": [ + "category", + "circuit_type", + "service_type", + "peering_type", + "status", + "a", + "b"], + "additionalProperties": False + }, + "related-service-info": { + "type": "object", + "properties": { + "name": {"type": "string"}, + "status": { + "type": "string", + "enum": ["operational", "installed", "planned", "ordered"] + }, + "circuit_type": { + "type": "string", + "enum": ["path", "service", "l2circuit"] + }, + "project": {"type": "string"} + }, + "additionalProperties": False + } + }, + + "type": "object", + "properties": { + "equipment name": {"type": "string"}, + "card id": {"type": "string"}, + "port number": {"type": "string"}, + "path": {"$ref": "#/definitions/path"}, + "related-services": { + "type": "array", + "items": {"$ref": "#/definitions/related-service-info"} + }, + }, + "required": ["equipment name", "card id", "port number"], + "additionalProperties": False +} diff --git a/test/test_classifier_routes.py b/test/test_classifier_routes.py index 01192f3175acc6164b8018de52cdf418ff29f2b7..83b358bf0fd8911e041612c45641b11cd3853538 100644 --- a/test/test_classifier_routes.py +++ b/test/test_classifier_routes.py @@ -127,6 +127,8 @@ def test_coriant_info( """ just check that entity_name is correctly parsed and the correct method is called, but mock out all sql access + + # TODO: schema validation """ CONNECTION = 'bogus connection' diff --git a/test/test_infinera_classifier.py b/test/test_infinera_classifier.py index 6e0621a08d20abdc737f95415bbbbca1cf8966b8..d1eb97821e8ed6dfc778ac6c4977e18902ce8eb4 100644 --- a/test/test_infinera_classifier.py +++ b/test/test_infinera_classifier.py @@ -1,146 +1,13 @@ import json import jsonschema +from inventory_provider.routes.classifier_schema \ + import INFINERA_LAMBDA_INFO_RESPONSE_SCHEMA DEFAULT_REQUEST_HEADERS = { "Content-type": "application/json", "Accept": ["application/json"] } -LOCATIONS_DEFINITIONS = { - "location-endpoint": { - "type": "object", - "properties": { - "equipment": {"type": "string"}, - "name": {"type": "string"}, - "abbreviation": {"type": "string"} - }, - "required": ["equipment", "name", "abbreviation"], - "additionalProperties": False - }, - "location": { - "type": "object", - "properties": { - "a": {"$ref": "#/definitions/location-endpoint"}, - "b": {"$ref": "#/definitions/location-endpoint"} - }, - "required": ["a"], - "additionalProperties": False - }, - "locations-list": { - "type": "array", - "items": {"$ref": "#/definitions/location"} - } -} - -INFINERA_LINK_METADATA_DEFINITIONS = { - "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"}, - "pop_name": {"type": "string"}, - "pop_abbreviation": {"type": "string"}, - "other_end_pop_name": {"type": "string"}, - "other_end_pop_abbreviation": {"type": "string"}, - "equipment": {"type": "string"}, - "other_end_equipment": {"type": "string"}, - "port": {"type": "string"}, - "other_end_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"} - }, - "additionalProperties": False - }, - "related-service-info": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "status": { - "type": "string", - "enum": ["operational", "installed", "planned", "ordered"] - }, - "circuit_type": { - "type": "string", - "enum": ["path", "service", "l2circuit"] - }, - "project": {"type": "string"} - }, - "required": ["name", "status", "circuit_type", "project"], - "additionalProperties": False - }, - "geant-lambda": { - "type": "object", - "properties": { - "id": {"type": "integer"}, - "name": {"type": "string"}, - "project": {"type": "string"}, - "status": { - "type": "string", - "enum": ["operational", "installed", "planned", "ordered"] - }, - }, - "additionalProperties": False - } -} - -INFINERA_LINK_METADATA = { - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - - "definitions": { - **INFINERA_LINK_METADATA_DEFINITIONS, **LOCATIONS_DEFINITIONS - }, - - "type": "object", - "properties": { - "services": { - "type": "array", - "items": {"$ref": "#/definitions/service-info"} - }, - "related-services": { - "type": "array", - "items": {"$ref": "#/definitions/related-service-info"} - }, - "geant-lambda": { - "$ref": "#/definitions/geant-lambda" - }, - "locations": {"$ref": "#/definitions/locations-list"} - }, - "additionalProperties": False -} - - def test_trap_metadata(client): rv = client.get( '/classifier/infinera-lambda-info/' @@ -149,4 +16,4 @@ def test_trap_metadata(client): assert rv.status_code == 200 assert rv.is_json response_data = json.loads(rv.data.decode('utf-8')) - jsonschema.validate(response_data, INFINERA_LINK_METADATA) + jsonschema.validate(response_data, INFINERA_LAMBDA_INFO_RESPONSE_SCHEMA)