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

Finished feature cache-vpn-rr-peers.

parents f1506d3d 585e47f0
No related branches found
No related tags found
No related merge requests found
...@@ -606,17 +606,21 @@ Any non-empty responses are JSON formatted messages. ...@@ -606,17 +606,21 @@ Any non-empty responses are JSON formatted messages.
* valid values: * valid values:
```json ```json
{ {
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"type": "object", "definitions": {
"properties": { "ip-address": {
"name": {
"type": "string", "type": "string",
"oneOf": [ "oneOf": [
{"pattern": r'^(\d+\.){3}\d+$'}, {"pattern": r'^(\d+\.){3}\d+$'},
{"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'} {"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'}
] ]
}, }
},
"type": "object",
"properties": {
"name": {"$ref": "#/definitions/ip-address"},
"description": {"type": "string"}, "description": {"type": "string"},
"as": { "as": {
"type": "object", "type": "object",
...@@ -632,3 +636,32 @@ Any non-empty responses are JSON formatted messages. ...@@ -632,3 +636,32 @@ Any non-empty responses are JSON formatted messages.
"additionalProperties": False "additionalProperties": False
} }
``` ```
`vpn_rr_peers/<address>`
* key examples
* `ix_public_peer:193.203.0.203`
* valid values:
```json
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"ip-address": {
"type": "string",
"oneOf": [
{"pattern": r'^(\d+\.){3}\d+$'},
{"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'}
]
}
},
"type": "object",
"properties": {
"name": {"$ref": "#/definitions/ip-address"},
"description": {"type": "string"},
"peer-as": {"type": "integer"}
},
"required": ["name", "description"],
"additionalProperties": False
}
```
...@@ -24,4 +24,4 @@ ...@@ -24,4 +24,4 @@
classifier metadata api classifier metadata api
read snmp community string from netconf read snmp community string from netconf
derive active router list from junosspace derive active router list from junosspace
cache ix public peers cache ix public & vpn rr peers
...@@ -275,6 +275,21 @@ def ix_public_peers(netconf_config): ...@@ -275,6 +275,21 @@ def ix_public_peers(netconf_config):
} }
def vpn_rr_peers(netconf_config):
for r in netconf_config.xpath(
'//configuration/logical-systems[name/text()="VRR"]/'
'/protocols/bgp/'
'group[name/text()="VPN-RR" or name/text()="VPN-RR-INTERNAL"]/'
'neighbor'):
neighbor = {
'name': ipaddress.ip_address(r.find('name').text).exploded,
'description': r.find('description').text,
}
peer_as = r.find('peer-as')
if peer_as is not None:
neighbor['peer-as'] = int(r.find('peer-as').text)
yield neighbor
# note for enabling vrr data parsing ... # note for enabling vrr data parsing ...
# def fetch_vrr_config(hostname, ssh_params): # def fetch_vrr_config(hostname, ssh_params):
# #
......
...@@ -255,6 +255,23 @@ def refresh_ix_public_peers(hostname, netconf): ...@@ -255,6 +255,23 @@ def refresh_ix_public_peers(hostname, netconf):
json.dumps(peer)) json.dumps(peer))
def refresh_vpn_rr_peers(hostname, netconf):
task_logger = logging.getLogger(constants.TASK_LOGGER_NAME)
task_logger.debug(
'removing cached vpn rr for %r' % hostname)
r = get_redis(InventoryTask.config)
for k in r.keys('vpn_rr_peer:*'):
value = json.loads(r.get(k.decode('utf-8')).decode('utf-8'))
if value['router'] == hostname:
r.delete(k)
for peer in juniper.vpn_rr_peers(netconf):
peer['router'] = hostname
r.set(
'vpn_rr_peer:' + peer['name'],
json.dumps(peer))
@app.task @app.task
def reload_router_config(hostname): def reload_router_config(hostname):
task_logger = logging.getLogger(constants.TASK_LOGGER_NAME) task_logger = logging.getLogger(constants.TASK_LOGGER_NAME)
...@@ -263,11 +280,12 @@ def reload_router_config(hostname): ...@@ -263,11 +280,12 @@ def reload_router_config(hostname):
netconf_refresh_config.apply(hostname) netconf_refresh_config.apply(hostname)
netconf_doc = load_netconf_data(hostname) netconf_doc = load_netconf_data(hostname)
if not netconf_doc: if netconf_doc is None:
task_logger.error('no netconf data available for %r' % hostname) task_logger.error('no netconf data available for %r' % hostname)
else: else:
refresh_ix_public_peers(hostname, netconf_doc) refresh_ix_public_peers(hostname, netconf_doc)
refresh_vpn_rr_peers(hostname, netconf_doc)
community = juniper.snmp_community_string(netconf_doc) community = juniper.snmp_community_string(netconf_doc)
if not community: if not community:
......
...@@ -12,14 +12,12 @@ TEST_DATA_DIRNAME = os.path.realpath(os.path.join( ...@@ -12,14 +12,12 @@ TEST_DATA_DIRNAME = os.path.realpath(os.path.join(
'test', 'test',
'data')) 'data'))
ROUTER_NAME = 'mx1.vie.at.geant.net'
@pytest.fixture @pytest.fixture
def netconf(): def netconf(router):
netconf_filename = os.path.join( netconf_filename = os.path.join(
TEST_DATA_DIRNAME, TEST_DATA_DIRNAME,
ROUTER_NAME + '-netconf.xml') router + '-netconf.xml')
doc = etree.parse(netconf_filename) doc = etree.parse(netconf_filename)
juniper.validate_netconf_config(doc) juniper.validate_netconf_config(doc)
return doc return doc
...@@ -30,15 +28,19 @@ def test_ix_public_peers(netconf): ...@@ -30,15 +28,19 @@ def test_ix_public_peers(netconf):
schema = { schema = {
"$schema": "http://json-schema.org/draft-07/schema#", "$schema": "http://json-schema.org/draft-07/schema#",
"type": "object", "definitions": {
"properties": { "ip-address": {
"name": {
"type": "string", "type": "string",
"oneOf": [ "oneOf": [
{"pattern": r'^(\d+\.){3}\d+$'}, {"pattern": r'^(\d+\.){3}\d+$'},
{"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'} {"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'}
] ]
}, }
},
"type": "object",
"properties": {
"name": {"$ref": "#/definitions/ip-address"},
"description": {"type": "string"}, "description": {"type": "string"},
"as": { "as": {
"type": "object", "type": "object",
...@@ -56,3 +58,36 @@ def test_ix_public_peers(netconf): ...@@ -56,3 +58,36 @@ def test_ix_public_peers(netconf):
for p in juniper.ix_public_peers(netconf): for p in juniper.ix_public_peers(netconf):
jsonschema.validate(p, schema) jsonschema.validate(p, schema)
print(p)
def test_vpn_rr_peers(netconf):
# there are actually no v6 addresses, pattern could be ommitted
# TODO: check if there's a robust justification for this
schema = {
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"ip-address": {
"type": "string",
"oneOf": [
{"pattern": r'^(\d+\.){3}\d+$'},
{"pattern": r'^([a-f\d]{4}:){7}[a-f\d]{4}$'}
]
}
},
"type": "object",
"properties": {
"name": {"$ref": "#/definitions/ip-address"},
"description": {"type": "string"},
"peer-as": {"type": "integer"}
},
"required": ["name", "description"],
"additionalProperties": False
}
for p in juniper.vpn_rr_peers(netconf):
jsonschema.validate(p, schema)
print(p)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment