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

refactored to share some code between both routes

parent 4e51b8ff
No related branches found
No related tags found
No related merge requests found
...@@ -176,36 +176,78 @@ def _load_interfaces(hostname): ...@@ -176,36 +176,78 @@ def _load_interfaces(hostname):
} }
def _load_poller_interfaces(hostname=None): def _add_bundle_parents(interfaces, hostname=None):
"""
generator that adds bundle-parents info to each interface.
snmp_indexes = _load_snmp_indexes(hostname) :param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with bundle-parents populated in each element
"""
bundles = _load_interface_bundles(hostname) bundles = _load_interface_bundles(hostname)
services = _load_services(hostname) for ifc in interfaces:
for ifc in _load_interfaces(hostname):
router_snmp = snmp_indexes.get(ifc['router'], None)
if not router_snmp or ifc['name'] not in router_snmp:
# there's no way to poll this interface
continue
ifc['snmp-index'] = router_snmp[ifc['name']]['index']
# TODO: uncomment this when it won't break poller-admin-service
# not urgent ... it looks empirically like all logical-system
# interfaces are repeated for both communities
# ifc['snmp-community'] = router_snmp[ifc['name']]['community']
router_bundle = bundles.get(ifc['router'], None) router_bundle = bundles.get(ifc['router'], None)
if router_bundle: if router_bundle:
base_ifc = ifc['name'].split('.')[0] base_ifc = ifc['name'].split('.')[0]
ifc['bundle-parents'] = router_bundle.get(base_ifc, []) ifc['bundle-parents'] = router_bundle.get(base_ifc, [])
yield ifc
def _add_circuits(interfaces, hostname=None):
"""
generator that adds service info to each interface.
:param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with 'circuits' populated in each element, if present
"""
services = _load_services(hostname)
for ifc in interfaces:
router_services = services.get(ifc['router'], None) router_services = services.get(ifc['router'], None)
if router_services: if router_services:
ifc['circuits'] = router_services.get(ifc['name'], []) ifc['circuits'] = router_services.get(ifc['name'], [])
yield ifc
def _add_snmp_indexes(interfaces, hostname=None):
"""
generator that adds snmp info to each interface, if available
:param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with 'snmp-index' optionally added to each element
"""
snmp_indexes = _load_snmp_indexes(hostname)
for ifc in interfaces:
router_snmp = snmp_indexes.get(ifc['router'], None)
if router_snmp and ifc['name'] in router_snmp:
ifc['snmp-index'] = router_snmp[ifc['name']]['index']
# TODO: uncomment this when it won't break poller-admin-service
# not urgent ... it looks empirically like all logical-system
# interfaces are repeated for both communities
# ifc['snmp-community'] = router_snmp[ifc['name']]['community']
yield ifc yield ifc
def _load_interfaces_to_poll(hostname=None):
"""
prepares the result of a call to /interfaces
:param hostname: hostname or None for all
:return: generator yielding interface elements
"""
basic_interfaces = _load_interfaces(hostname)
with_bundles = _add_bundle_parents(basic_interfaces, hostname)
with_circuits = _add_circuits(with_bundles, hostname)
with_snmp = _add_snmp_indexes(with_circuits, hostname)
def _has_snmp_index(ifc):
return 'snmp-index' in ifc
# only return interfaces that can be polled
return filter(_has_snmp_index, with_snmp)
@routes.route("/interfaces", methods=['GET', 'POST']) @routes.route("/interfaces", methods=['GET', 'POST'])
@routes.route('/interfaces/<hostname>', methods=['GET', 'POST']) @routes.route('/interfaces/<hostname>', methods=['GET', 'POST'])
@common.require_accepts_json @common.require_accepts_json
...@@ -236,7 +278,7 @@ def interfaces(hostname=None): ...@@ -236,7 +278,7 @@ def interfaces(hostname=None):
if result: if result:
result = result.decode('utf-8') result = result.decode('utf-8')
else: else:
result = list(_load_poller_interfaces(hostname)) result = list(_load_interfaces_to_poll(hostname))
if not result: if not result:
return Response( return Response(
response='no interfaces found', response='no interfaces found',
...@@ -250,6 +292,60 @@ def interfaces(hostname=None): ...@@ -250,6 +292,60 @@ def interfaces(hostname=None):
return Response(result, mimetype="application/json") return Response(result, mimetype="application/json")
def interface_speed(ifc):
"""
Return the maximum bits per second expected for the given interface.
cf. https://www.juniper.net/documentation/us/en/software/
vmx/vmx-getting-started/topics/task/
vmx-chassis-interface-type-configuring.html
:param ifc:
:return: an integer bits per second
"""
GB = 1000000000
# GB = 1 << 30
def _name_to_speed(ifc_name):
if ifc_name.startswith('ge'):
return GB
if ifc_name.startswith('xe'):
return 10 * GB
if ifc_name.startswith('et'):
return 100 * GB
logger.warning(f'unrecognized interface name: {ifc_name}')
return -1
if ifc['bundle-parents']:
if not ifc['name'].startswith('ae'):
logger.warning(
f'ifc has bundle-parents, but name is {ifc["name"]}')
return sum(_name_to_speed(name) for name in ifc['bundle-parents'])
return _name_to_speed(ifc['name'])
def _load_interfaces_and_speeds(hostname=None):
"""
prepares the result of a call to /speeds
:param hostname: hostname or None for all
:return: generator yielding interface elements
"""
basic_interfaces = _load_interfaces(hostname)
with_bundles = _add_bundle_parents(basic_interfaces, hostname)
with_bundles = list(with_bundles)
def _result_ifc(ifc):
return {
'router': ifc['router'],
'name': ifc['name'],
'speed': interface_speed(ifc)
}
return map(_result_ifc, with_bundles)
@routes.route("/speeds", methods=['GET', 'POST']) @routes.route("/speeds", methods=['GET', 'POST'])
@routes.route('/speeds/<hostname>', methods=['GET', 'POST']) @routes.route('/speeds/<hostname>', methods=['GET', 'POST'])
@common.require_accepts_json @common.require_accepts_json
...@@ -260,8 +356,9 @@ def interface_speeds(hostname=None): ...@@ -260,8 +356,9 @@ def interface_speeds(hostname=None):
which returns information for either all interfaces which returns information for either all interfaces
or those on the requested hostname. or those on the requested hostname.
The response is a list of speed information for all The response is a list of maximum speed information (in bits
known interfaces. per second) for all known interfaces.
[speed <= 0 means the max interface speed can't be determined]
.. asjson:: .. asjson::
inventory_provider.routes.poller.INTERFACE_SPEED_LIST_SCHEMA inventory_provider.routes.poller.INTERFACE_SPEED_LIST_SCHEMA
...@@ -279,20 +376,7 @@ def interface_speeds(hostname=None): ...@@ -279,20 +376,7 @@ def interface_speeds(hostname=None):
if result: if result:
result = result.decode('utf-8') result = result.decode('utf-8')
else: else:
result = list(_load_interfaces_and_speeds(hostname))
def _speed(ifc):
# TODO
return -1
def _result_ifc(ifc):
return {
'router': ifc['router'],
'name': ifc['name'],
'speed': _speed(ifc)
}
result = list(map(_result_ifc, _load_interfaces(hostname)))
if not result: if not result:
return Response( return Response(
response='no interfaces found', response='no interfaces found',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment