Skip to content
Snippets Groups Projects
Commit ac604cc8 authored by geant-release-service's avatar geant-release-service
Browse files

Finished release 0.126.

parents 94f4bc89 0132cc6f
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [0.126] - 2024-08-13
- DBOARD3-998: Skipped router during update if no data retrieved and no cached data found
- DBOARD3-997: excluded pxc ports and related lags for Nokia routers
- DBOARD3-996: added TimeoutExpiredError to handled exceptions
- DBOARD3-987: added interfaces from other stanzas for Nokia routers
- DBOARD3-958: added BGP peer extraction for Nokia routers
## [0.125] - 2024-07-18 ## [0.125] - 2024-07-18
- DBOARD3-971: Added handling for GRV 10G interfaces - DBOARD3-971: Added handling for GRV 10G interfaces
- POL1-836: Included PHY RE_INTERCONNECT in R&E Peer dashboards - POL1-836: Included PHY RE_INTERCONNECT in R&E Peer dashboards
......
...@@ -11,6 +11,8 @@ from jnpr.junos import exception as EzErrors ...@@ -11,6 +11,8 @@ from jnpr.junos import exception as EzErrors
from lxml import etree from lxml import etree
import netifaces import netifaces
from inventory_provider.tasks.common import asn_to_int
CONFIG_SCHEMA = """<?xml version="1.1" encoding="UTF-8" ?> CONFIG_SCHEMA = """<?xml version="1.1" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
...@@ -280,36 +282,6 @@ def list_interfaces(netconf_config): ...@@ -280,36 +282,6 @@ def list_interfaces(netconf_config):
yield u yield u
def asn_to_int(asn_string: str) -> int:
"""
Convert a possibly dotted ASN to an integer.
Args:
asn_string (str): ASN to be converted, can be in dot notation or not.
Returns:
int: ASN in integer format.
Raises:
ValueError: If the ASN string is not in the expected format or exceeds valid range.
"""
dotted_asn_pattern = re.compile(r'^(\d+)\.(\d+)$')
match = dotted_asn_pattern.match(asn_string)
if match:
high_order, low_order = map(int, match.groups())
if high_order > 0xffff or low_order > 0xffff:
raise ValueError(f'Invalid ASN format: {asn_string}. Both components must be <= 0xffff.')
return (high_order << 16) | low_order
elif asn_string.isdigit():
return int(asn_string)
else:
raise ValueError(f'Unable to parse ASN string: {asn_string}. Expected either a pure integer or a dot notation.')
def _system_bgp_peers(system_node): def _system_bgp_peers(system_node):
def _peering_params(neighbor_node): def _peering_params(neighbor_node):
address = neighbor_node.find('name').text address = neighbor_node.find('name').text
......
from lxml import etree import ipaddress
import logging import logging
import re import re
from functools import lru_cache
from lxml import etree
from ncclient import manager, xml_ from ncclient import manager, xml_
from inventory_provider.tasks.common import asn_to_int
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
BREAKOUT_PATTERN = re.compile( BREAKOUT_PATTERN = re.compile(
...@@ -88,6 +92,11 @@ def remove_xml_namespaces(etree_doc): ...@@ -88,6 +92,11 @@ def remove_xml_namespaces(etree_doc):
return etree_doc return etree_doc
def _get_admin_state_from_element(element):
admin_state_element = element.find('admin-state')
return admin_state_element.text if admin_state_element is not None else 'enable'
def load_docs(hostname, ssh_params): def load_docs(hostname, ssh_params):
""" """
Load the running and state docs for the given hostname Load the running and state docs for the given hostname
...@@ -165,13 +174,25 @@ def get_interfaces_state(state_doc): ...@@ -165,13 +174,25 @@ def get_interfaces_state(state_doc):
yield details yield details
@lru_cache
def get_pxc_ports(netconf_config):
# these ports will be ignored for the purposes of the update
pxc_ports = set()
for port in netconf_config.findall('./configure/port-xc/pxc'):
pxc_ports.add(port.find('port-id').text)
for port in netconf_config.findall('./configure/port'):
port_id = port.find('port-id').text
if port_id.startswith('pxc'):
pxc_ports.add(port_id)
return pxc_ports
def get_ports_config(netconf_config): def get_ports_config(netconf_config):
def _port_info(e): def _port_info(e):
pi = { pi = {
'port-id': e.find('port-id').text 'port-id': e.find('port-id').text,
'admin-state': _get_admin_state_from_element(e)
} }
admin_state = e.find('admin-state')
pi['admin-state'] = admin_state.text if admin_state is not None else 'enabled' # assume enabled if not present
description = e.find('description') description = e.find('description')
pi['description'] = description.text if description is not None else '' pi['description'] = description.text if description is not None else ''
...@@ -186,10 +207,14 @@ def get_ports_config(netconf_config): ...@@ -186,10 +207,14 @@ def get_ports_config(netconf_config):
breakout_match.group('unit'), 'Unknown') breakout_match.group('unit'), 'Unknown')
return pi return pi
pxc_ports = get_pxc_ports(netconf_config)
# making the assumption that the breakout ports are listed directly before their # making the assumption that the breakout ports are listed directly before their
current_parent_port = None current_parent_port = None
# child ports # child ports
for port in netconf_config.findall('./configure/port'): for port in netconf_config.findall('./configure/port'):
port_id = port.find('port-id').text
if port_id in pxc_ports:
continue
port_info = _port_info(port) port_info = _port_info(port)
if 'breakout' in port_info: if 'breakout' in port_info:
current_parent_port = port_info current_parent_port = port_info
...@@ -205,42 +230,42 @@ def get_lags_config(netconf_config): ...@@ -205,42 +230,42 @@ def get_lags_config(netconf_config):
enabled_ports = { enabled_ports = {
p['port-id'] for p in get_ports_config(netconf_config) if p['admin-state'] == 'enable' p['port-id'] for p in get_ports_config(netconf_config) if p['admin-state'] == 'enable'
} }
pxc_ports = get_pxc_ports(netconf_config)
def _lag_info(e): def _lag_info(e):
_name = e.find('./lag-name').text _name = e.find('./lag-name').text
port_elements = e.findall('./port') port_elements = e.findall('./port')
port_ids = (p.find('./port-id').text for p in port_elements) port_ids = (p.find('./port-id').text for p in port_elements)
admin_state = e.find('./admin-state')
description_e = e.find('description') description_e = e.find('description')
ifc = { ifc = {
'name': _name, 'name': _name,
'description': ( 'description': description_e.text if description_e is not None else '',
description_e.text if description_e is not None else '' 'admin-state': _get_admin_state_from_element(e),
),
'admin-state': admin_state.text if admin_state is not None else 'enabled', # assume enabled if not present
'ports': [p_id for p_id in port_ids if p_id in enabled_ports], 'ports': [p_id for p_id in port_ids if p_id in enabled_ports],
} }
return ifc return ifc
for lag in netconf_config.findall('./configure/lag'): for lag in netconf_config.findall('./configure/lag'):
ports = {p.find('./port-id').text for p in lag.findall('./port')}
if pxc_ports > ports:
continue
yield _lag_info(lag) yield _lag_info(lag)
def get_interfaces_config(netconf_config): def get_interfaces_config(netconf_config):
for interface in netconf_config.findall('configure/router/interface'): for interface in netconf_config.xpath('configure/router/interface '
'| configure/service/vprn/interface '
'| configure/service/ies/interface'):
details = { details = {
"interface-name": interface.find('interface-name').text, "interface-name": interface.find('interface-name').text,
"ipv4": [], "ipv4": [],
"ipv6": [], "ipv6": [],
'admin-state': _get_admin_state_from_element(interface)
} }
description = interface.find('description') description = interface.find('description')
details["description"] = description.text if description is not None else "" details["description"] = description.text if description is not None else ""
admin_state = interface.find('admin-state')
if admin_state is not None:
details["admin-state"] = admin_state.text
for element in interface.xpath('ipv4/primary | ipv4/secondary'): for element in interface.xpath('ipv4/primary | ipv4/secondary'):
address = element.find('address').text address = element.find('address').text
prefix_length = element.find('prefix-length').text prefix_length = element.find('prefix-length').text
...@@ -252,3 +277,59 @@ def get_interfaces_config(netconf_config): ...@@ -252,3 +277,59 @@ def get_interfaces_config(netconf_config):
details["ipv6"].append(f'{address}/{prefix_length}') details["ipv6"].append(f'{address}/{prefix_length}')
yield details yield details
def _get_neighbors_by_group(neighbor_elements):
neighbors_by_group = {}
for neighbor in neighbor_elements:
# admin_state = _get_admin_state_from_element(neighbor) # do we want to do anything with this?
group_name = neighbor.find('group').text
address = neighbor.find('ip-address').text
info = {
'address': ipaddress.ip_address(address).exploded
}
peer_as = neighbor.find('peer-as')
if peer_as is not None:
info['remote-asn'] = asn_to_int(peer_as.text)
description = neighbor.find('description')
if description is not None:
info['description'] = description.text
neighbors_by_group.setdefault(group_name, []).append(info)
return neighbors_by_group
def get_peer_info(neighbors_by_group, group_elements):
for bgp_group in group_elements:
# admin_state = _get_admin_state_from_element(bgp_group) # do we want to do anything with this?
group_name = bgp_group.find('group-name').text
details = {
'group': group_name
}
local_as = bgp_group.find('local-as')
if local_as is not None:
asn_value_node = local_as.find('as-number')
details['local-asn'] = asn_to_int(asn_value_node.text)
for neighbor in neighbors_by_group.get(group_name, []):
neighbor.update(details)
yield neighbor
def get_router_peers(netconf_config):
neighbors_by_group = _get_neighbors_by_group(netconf_config.xpath('configure/router/bgp/neighbor'))
group_elements = netconf_config.xpath('configure/router/bgp/group')
yield from get_peer_info(neighbors_by_group, group_elements)
def get_all_vprn_peers(netconf_config):
for vprn in netconf_config.xpath('configure/service/vprn'):
service_name = vprn.find('service-name').text
neighbors_by_group = _get_neighbors_by_group(vprn.xpath('bgp/neighbor'))
group_elements = vprn.xpath('bgp/group')
for peer in get_peer_info(neighbors_by_group, group_elements):
peer['instance'] = service_name # just to match the data from Juniper
yield peer
def get_all_bgp_peers(netconf_config):
yield from get_router_peers(netconf_config)
yield from get_all_vprn_peers(netconf_config)
...@@ -255,3 +255,33 @@ def ims_sorted_service_type_key(service_type): ...@@ -255,3 +255,33 @@ def ims_sorted_service_type_key(service_type):
# prettification ... e.g. no trailing _ for 'MD-VPN (NATIVE)' # prettification ... e.g. no trailing _ for 'MD-VPN (NATIVE)'
service_type = re.sub('_+$', '', service_type) service_type = re.sub('_+$', '', service_type)
return re.sub('^_+', '', service_type) return re.sub('^_+', '', service_type)
def asn_to_int(asn_string: str) -> int:
"""
Convert a possibly dotted ASN to an integer.
Args:
asn_string (str): ASN to be converted, can be in dot notation or not.
Returns:
int: ASN in integer format.
Raises:
ValueError: If the ASN string is not in the expected format or exceeds valid range.
"""
dotted_asn_pattern = re.compile(r'^(\d+)\.(\d+)$')
match = dotted_asn_pattern.match(asn_string)
if match:
high_order, low_order = map(int, match.groups())
if high_order > 0xffff or low_order > 0xffff:
raise ValueError(f'Invalid ASN format: {asn_string}. Both components must be <= 0xffff.')
return (high_order << 16) | low_order
elif asn_string.isdigit():
return int(asn_string)
else:
raise ValueError(f'Unable to parse ASN string: {asn_string}. Expected either a pure integer or a dot notation.')
...@@ -7,6 +7,7 @@ import logging ...@@ -7,6 +7,7 @@ import logging
import os import os
import re import re
import ncclient.operations
import ncclient.transport.errors import ncclient.transport.errors
from celery import Task, states, chord from celery import Task, states, chord
from celery.result import AsyncResult from celery.result import AsyncResult
...@@ -609,6 +610,8 @@ def _reload_router_config_nokia( ...@@ -609,6 +610,8 @@ def _reload_router_config_nokia(
f'loading netconf data for {"lab " if lab else ""} {hostname}') f'loading netconf data for {"lab " if lab else ""} {hostname}')
netconf_doc, state_doc = retrieve_and_persist_config_nokia( netconf_doc, state_doc = retrieve_and_persist_config_nokia(
hostname, lab, warning_callback) hostname, lab, warning_callback)
if netconf_doc is None or state_doc is None:
return
r = get_next_redis(InventoryTask.config) r = get_next_redis(InventoryTask.config)
refresh_nokia_interface_list(hostname, netconf_doc, r, lab) refresh_nokia_interface_list(hostname, netconf_doc, r, lab)
communities = _nokia_community_strings(InventoryTask.config) communities = _nokia_community_strings(InventoryTask.config)
...@@ -644,12 +647,13 @@ def retrieve_and_persist_config_nokia( ...@@ -644,12 +647,13 @@ def retrieve_and_persist_config_nokia(
if not state_str: if not state_str:
failed_docs.append('port state') failed_docs.append('port state')
failed_keys.append(redis_state_key) failed_keys.append(redis_state_key)
update_callback(f'no cached info for {failed_keys}')
if failed_docs: if failed_docs:
raise InventoryTaskError( update_callback(f'no cached info for {failed_keys}. Ignoring this host')
logger.warning(
f'Nokia doc error with {hostname}' f'Nokia doc error with {hostname}'
f' and no cached data found for {failed_docs}' f' and no cached data found for {failed_docs}. Ignoring this host'
) )
return None, None
netconf_config = nokia.remove_xml_namespaces(etree.fromstring(netconf_str)) netconf_config = nokia.remove_xml_namespaces(etree.fromstring(netconf_str))
state = nokia.remove_xml_namespaces(etree.fromstring(state_str)) state = nokia.remove_xml_namespaces(etree.fromstring(state_str))
update_callback(f'Returning cached nokia data for {hostname}') update_callback(f'Returning cached nokia data for {hostname}')
...@@ -946,7 +950,8 @@ def retrieve_and_persist_interface_info_juniper( ...@@ -946,7 +950,8 @@ def retrieve_and_persist_interface_info_juniper(
try: try:
interface_info_str = juniper.get_interface_info_for_router(hostname, InventoryTask.config["ssh"]) interface_info_str = juniper.get_interface_info_for_router(hostname, InventoryTask.config["ssh"])
logger.info(f'interface-info rpc success from {hostname}') logger.info(f'interface-info rpc success from {hostname}')
except (ConnectionError, juniper.TimeoutError, InventoryTaskError, ncclient.transport.errors.SSHError): except (ConnectionError, juniper.TimeoutError, InventoryTaskError,
ncclient.transport.errors.SSHError, ncclient.operations.errors.TimeoutExpiredError):
msg = f'error loading interface-info data from {hostname}' msg = f'error loading interface-info data from {hostname}'
logger.exception(msg) logger.exception(msg)
update_callback(msg) update_callback(msg)
......
...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages ...@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup( setup(
name='inventory-provider', name='inventory-provider',
version="0.125", version="0.126",
author='GEANT', author='GEANT',
author_email='swd@geant.org', author_email='swd@geant.org',
description='Dashboard inventory provider', description='Dashboard inventory provider',
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ from lxml import etree ...@@ -7,7 +7,7 @@ from lxml import etree
import pytest import pytest
from inventory_provider import juniper from inventory_provider import juniper
from inventory_provider.juniper import asn_to_int from inventory_provider.tasks.common import asn_to_int
NETIFACES_TEST_DATA_STRING = """{ NETIFACES_TEST_DATA_STRING = """{
'lo0': {{AF_INET}: [{'addr': '127.0.0.1', 'netmask': '255.0.0.0', 'peer': '127.0.0.1'}], 'lo0': {{AF_INET}: [{'addr': '127.0.0.1', 'netmask': '255.0.0.0', 'peer': '127.0.0.1'}],
......
import ipaddress
import os import os
import pathlib import pathlib
from copy import deepcopy
from functools import lru_cache from functools import lru_cache
import pytest import pytest
...@@ -10,7 +12,7 @@ from inventory_provider import nokia ...@@ -10,7 +12,7 @@ from inventory_provider import nokia
PORT_SCHEMA = { PORT_SCHEMA = {
'$schema': 'https://json-schema.org/draft-07/schema#', '$schema': 'https://json-schema.org/draft/2020-12/schema',
'type': 'object', 'type': 'object',
'properties': { 'properties': {
'port-id': {'type': 'string'}, 'port-id': {'type': 'string'},
...@@ -23,6 +25,21 @@ PORT_SCHEMA = { ...@@ -23,6 +25,21 @@ PORT_SCHEMA = {
'additionalProperties': True 'additionalProperties': True
} }
PEERS_SCHEMA = {
'$schema': 'https://json-schema.org/draft/2020-12/schema',
'type': 'object',
'properties': {
'address': {'type': 'string'},
'remote-asn': {'type': 'integer'},
'local-asn': {'type': 'integer'},
'description': {'type': 'string'},
'group': {'type': 'string'},
'instance': {'type': 'string'}
},
'required': ['address', 'group'],
'additionalProperties': False
}
@lru_cache @lru_cache
def _load_xml_doc(filename): def _load_xml_doc(filename):
...@@ -47,6 +64,13 @@ state_doc = nokia.remove_xml_namespaces(etree.parse(pathlib.Path(__file__).paren ...@@ -47,6 +64,13 @@ state_doc = nokia.remove_xml_namespaces(etree.parse(pathlib.Path(__file__).paren
@pytest.mark.parametrize('hostname,expected_bundles', [ @pytest.mark.parametrize('hostname,expected_bundles', [
('rt0.ams.nl.lab.office.geant.net', {
'lag-1': ['1/1/c2/1'],
'lag-2': ['1/1/c5/1'],
'lag-4': ['1/1/c8/1'],
'lag-5': ['1/1/c11/1', '2/1/c11/1'],
'lag-6': ['2/1/c8/1'],
'lag-11': ['1/1/c2/3']}),
('rt0.ams.nl.geant.net', { ('rt0.ams.nl.geant.net', {
'lag-5': ['1/1/c19/1', '2/1/c19/1'], 'lag-5': ['1/1/c19/1', '2/1/c19/1'],
'lag-8': ['1/1/c1/1', '1/1/c5/1'], 'lag-8': ['1/1/c1/1', '1/1/c5/1'],
...@@ -66,6 +90,17 @@ def test_get_lags(hostname, expected_bundles): ...@@ -66,6 +90,17 @@ def test_get_lags(hostname, expected_bundles):
@pytest.mark.parametrize( @pytest.mark.parametrize(
'hostname,all_expected_data', [ 'hostname,all_expected_data', [
('rt0.ams.nl.lab.office.geant.net', (
('lag-1.0', {'62.40.119.88/31'}, {'2001:799:1ab:2::31/126'}),
('lag-2.0', {'62.40.119.90/31'}, {'2001:799:1ab:2::41/126'}),
('lag-4.0', {'62.40.119.98/31'}, {'2001:799:1ab:2::55/126'}),
('lag-5.0', {'62.40.119.100/31'}, {'2001:799:1ab:2::59/126'}),
('lag-6.0', {'62.40.119.102/31'}, {'2001:799:1ab:2::5d/126'}),
('system', {'62.40.119.6/32'}, {'2001:799:1ab::6/128'}),
('lag-11:100', {'62.40.124.217/30'}, {'2001:798:14:10aa::9/126'}),
('LAG-11.333', {'83.97.88.245/30'}, {'2001:7f8:3c::35/126'}),
('LAG-11.111', {'62.40.126.184/31'}, {'2001:798:111:1::31/126'}),
)),
('rt0.ams.nl.geant.net', ( ('rt0.ams.nl.geant.net', (
('lag-5.0', {'62.40.98.39/31'}, {'2001:798:cc::62/126'}), ('lag-5.0', {'62.40.98.39/31'}, {'2001:798:cc::62/126'}),
('lag-8.0', {'62.40.98.20/31'}, {'2001:798:cc::21/126'}), ('lag-8.0', {'62.40.98.20/31'}, {'2001:798:cc::21/126'}),
...@@ -89,7 +124,7 @@ def test_get_lags(hostname, expected_bundles): ...@@ -89,7 +124,7 @@ def test_get_lags(hostname, expected_bundles):
)), )),
]) ])
def test_interface_info(hostname, all_expected_data): def test_interface_info(hostname, all_expected_data):
netconf_doc = nokia.remove_xml_namespaces(_load_netconf_config(hostname=hostname)) netconf_doc = _load_netconf_config(hostname=hostname)
interfaces_by_id = {ifc['interface-name']: ifc for ifc in interfaces_by_id = {ifc['interface-name']: ifc for ifc in
nokia.get_interfaces_config(netconf_doc)} nokia.get_interfaces_config(netconf_doc)}
assert len(interfaces_by_id) == len(all_expected_data) assert len(interfaces_by_id) == len(all_expected_data)
...@@ -101,6 +136,7 @@ def test_interface_info(hostname, all_expected_data): ...@@ -101,6 +136,7 @@ def test_interface_info(hostname, all_expected_data):
@pytest.mark.parametrize('hostname,port_count', [ @pytest.mark.parametrize('hostname,port_count', [
('rt0.ams.nl.lab.office.geant.net', 65),
('rt0.ams.nl.geant.net', 66), ('rt0.ams.nl.geant.net', 66),
('rt0.fra.de.geant.net', 58), ('rt0.fra.de.geant.net', 58),
('rt0.gen.ch.geant.net', 141), ('rt0.gen.ch.geant.net', 141),
...@@ -108,7 +144,7 @@ def test_interface_info(hostname, all_expected_data): ...@@ -108,7 +144,7 @@ def test_interface_info(hostname, all_expected_data):
('rt0.lon2.uk.geant.net', 139), ('rt0.lon2.uk.geant.net', 139),
]) ])
def test_get_ports(hostname, port_count): def test_get_ports(hostname, port_count):
netconf_doc = nokia.remove_xml_namespaces(_load_netconf_config(hostname=hostname)) netconf_doc = _load_netconf_config(hostname=hostname)
ports = list(nokia.get_ports_config(netconf_doc)) ports = list(nokia.get_ports_config(netconf_doc))
assert len(ports) == port_count assert len(ports) == port_count
...@@ -167,3 +203,29 @@ def test_snmp_index(): ...@@ -167,3 +203,29 @@ def test_snmp_index():
"management": 1280, "management": 1280,
} }
assert {ifc["interface-name"]: ifc["if-index"] for ifc in interfaces} == expected assert {ifc["interface-name"]: ifc["if-index"] for ifc in interfaces} == expected
@pytest.mark.parametrize('hostname', [
'rt0.ams.nl.lab.office.geant.net',
'rt0.ams.nl.geant.net',
'rt0.fra.de.geant.net',
'rt0.gen.ch.geant.net',
'rt0.lon.uk.geant.net',
'rt0.lon2.uk.geant.net'
])
def test_get_peers(hostname):
netconf_doc = _load_netconf_config(hostname)
all_peers_from_doc = set()
all_peers_from_call = set()
for neighbor_element in netconf_doc.xpath('//bgp/neighbor'):
address = neighbor_element.find('ip-address').text
all_peers_from_doc.add(ipaddress.ip_address(address).exploded)
for peer in nokia.get_all_vprn_peers(netconf_doc):
jsonschema.validate(peer, PEERS_SCHEMA)
all_peers_from_call.add(peer['address'])
router_peers_schema = deepcopy(PEERS_SCHEMA)
del router_peers_schema['properties']['instance']
for peer in nokia.get_router_peers(netconf_doc):
jsonschema.validate(peer, PEERS_SCHEMA)
all_peers_from_call.add(peer['address'])
assert all_peers_from_doc == all_peers_from_call
...@@ -3,13 +3,16 @@ import pathlib ...@@ -3,13 +3,16 @@ import pathlib
import jsonschema import jsonschema
from lxml import etree from lxml import etree
from ncclient.transport import TransportError
from inventory_provider.nokia import remove_xml_namespaces from inventory_provider.nokia import remove_xml_namespaces
from inventory_provider.tasks import common from inventory_provider.tasks import common
from inventory_provider.tasks.worker import populate_error_report_interfaces_cache, transform_ims_data, \ from inventory_provider.tasks.worker import populate_error_report_interfaces_cache, \
transform_ims_data, \
extract_ims_data, persist_ims_data, \ extract_ims_data, persist_ims_data, \
retrieve_and_persist_neteng_managed_device_list, \ retrieve_and_persist_neteng_managed_device_list, \
populate_poller_interfaces_cache, refresh_nokia_interface_list populate_poller_interfaces_cache, refresh_nokia_interface_list, \
retrieve_and_persist_config_nokia
def test_extract_ims_data(mocker): def test_extract_ims_data(mocker):
...@@ -870,7 +873,7 @@ def test_refresh_nokia_interface_list(mocked_redis, data_config): ...@@ -870,7 +873,7 @@ def test_refresh_nokia_interface_list(mocked_redis, data_config):
interface_hosts = json.loads(r.get( interface_hosts = json.loads(r.get(
'lab:netconf-interfaces-hosts:rt0.lon.uk.lab.office.geant.net' 'lab:netconf-interfaces-hosts:rt0.lon.uk.lab.office.geant.net'
).decode('utf-8')) ).decode('utf-8'))
assert len(interface_hosts) == 9 assert len(interface_hosts) == 15
interface_hosts_schema = { interface_hosts_schema = {
'$schema': 'http://json-schema.org/draft-07/schema#', '$schema': 'http://json-schema.org/draft-07/schema#',
...@@ -1064,3 +1067,13 @@ def test_populate_error_report_interfaces_cache(mocker, data_config, mocked_redi ...@@ -1064,3 +1067,13 @@ def test_populate_error_report_interfaces_cache(mocker, data_config, mocked_redi
nokia_router = r.get("classifier-cache:error-report-interfaces:rt0.geant.net") nokia_router = r.get("classifier-cache:error-report-interfaces:rt0.geant.net")
assert json.loads(nokia_router) == exp_nokia_router_interfaces assert json.loads(nokia_router) == exp_nokia_router_interfaces
def test_nokia_retrieval_failure(mocker, data_config, mocked_redis):
mocker.patch('inventory_provider.tasks.worker.InventoryTask.config')
mocker.patch("inventory_provider.tasks.worker.nokia.load_docs", side_effect=TransportError("Mocked TransportError"))
r = common._get_redis(data_config)
mocker.patch('inventory_provider.tasks.worker.get_current_redis', return_value=r)
config_doc, state_doc = retrieve_and_persist_config_nokia("unknown.router.geant.net")
assert config_doc is None
assert state_doc is None
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment