diff --git a/inventory_provider/juniper.py b/inventory_provider/juniper.py index 4a08c5233edb47e3e88ae168bc88641d3e4d97f9..89fd9207690aed6ae89a86fd947c29d4d2c81b98 100644 --- a/inventory_provider/juniper.py +++ b/inventory_provider/juniper.py @@ -211,6 +211,42 @@ def list_interfaces(netconf_config): for u in _units(name.text, i): yield u +def all_bgp_peers(netconf_config): + + def _peering_params(neighbor_node): + info = {'address': neighbor_node.find('name').text} + peer_as = neighbor_node.find('peer-as') + if peer_as is not None: + # lxml usage warning: can't just test `if peer_as:` + info['peer-as'] = int(peer_as.text) + description = neighbor_node.find('description') + if description is not None: + # lxml usage warning: can't just test `if description:` + info['description'] = description.text + return info + + for instance in netconf_config.xpath( + '//configuration/routing-instances/instance'): + instance_name = instance.find('name').text + for group in instance.xpath('./protocols/bgp/group'): + group_name = group.find('name').text + for neighbor in group.xpath('./neighbor'): + peer = _peering_params(neighbor) + peer['instance'] = instance_name + peer['group'] = group_name + yield peer + + for logical_system in netconf_config.xpath( + '//configuration/logical-systems'): + logical_system_name = logical_system.find('name').text + for group in logical_system.xpath('./protocols/bgp/group'): + group_name = group.find('name').text + for neighbor in group.xpath('./neighbor'): + peer = _peering_params(neighbor) + peer['logical-system'] = logical_system_name + peer['group'] = group_name + yield peer + def list_bgp_routes(netconf_config): for r in netconf_config.xpath( diff --git a/inventory_provider/routes/testing.py b/inventory_provider/routes/testing.py index 35357564a33d3e248cadfc5cadeb0b18db096b0d..81a43cf0db6f0b0ec48f1c0266f6479f6f8ea0fc 100644 --- a/inventory_provider/routes/testing.py +++ b/inventory_provider/routes/testing.py @@ -169,7 +169,7 @@ def bgp_configs(hostname): status=404, mimetype="text/html") - routes = list(juniper.list_bgp_routes( + routes = list(juniper.all_bgp_peers( etree.XML(netconf_string.decode('utf-8')))) if not routes: return Response( diff --git a/test/per_router/test_juniper_data.py b/test/per_router/test_juniper_data.py index d76f2c2e6bc5a9abd17290b49c3af74b03cbd147..60aaad6649f8288b3786a0473f0b6c6aae03a06d 100644 --- a/test/per_router/test_juniper_data.py +++ b/test/per_router/test_juniper_data.py @@ -35,33 +35,53 @@ def test_interface_list(netconf_doc): assert interfaces # at least shouldn't be empty -def test_bgp_list(netconf_doc): +def test_bgp_peering_data(netconf_doc): schema = { "$schema": "http://json-schema.org/draft-07/schema#", - "type": "array", - "items": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "description": {"type": "string"}, - "as": { - "type": "object", - "properties": { - "local": {"type": "integer"}, - "peer": {"type": "integer"}, - }, - "required": ["local", "peer"], - "additionalProperties": False - } + "definitions": { + "instance-peering": { + "type": "object", + "properties": { + "instance": {"type": "string"}, + "group": {"type": "string"}, + "description": {"type": "string"}, + "address": {"type": "string"}, + "peer-as": {"type": "integer"} + }, + # description is not always present, just based on + # empirical tests - not a problem + "required": ["instance", "group", "address", "peer-as"], + "additionalProperties": False }, - "required": ["name", "description", "as"], - "additionalProperties": False - } + "logical-system-peering": { + "type": "object", + "properties": { + "logical-system": {"type": "string"}, + "group": {"type": "string"}, + "description": {"type": "string"}, + "address": {"type": "string"}, + "peer-as": {"type": "integer"} + }, + # peer-as and/or description are not always present, + # just based on empirical tests - not a problem + "required": ["logical-system", "group", "address"], + "additionalProperties": False + }, + "peering": { + "oneOf": [ + {"$ref": "#/definitions/instance-peering"}, + {"$ref": "#/definitions/logical-system-peering"} + ] + } + }, + "type": "array", + "items": {"$ref": "#/definitions/peering"} } - routes = list(juniper.list_bgp_routes(netconf_doc)) - jsonschema.validate(routes, schema) + peerings = list(juniper.all_bgp_peers(netconf_doc)) + jsonschema.validate(peerings, schema) + assert peerings # there's always at least one def test_snmp_community_string(mocked_netifaces, netconf_doc):